Summary
SMSService._on_delivery_report() assumes the second comma-separated field in a +CMGR status-report response is the recipient. For text-mode status reports that include a message reference before the recipient, it emits recipient="6" and leaves reference=0, so delivery reports cannot be correlated back to the sent SMS reference.
Affected source
callstack/sms/service.py:229-258
- manually uses
line.split(",") on a quoted modem response.
- sets
recipient = parts[1].strip().strip('"').
- never populates the
SMSDeliveryReportEvent.reference field even though events/types.py:70-74 defines it.
tests/test_delivery_reports.py verifies _RawDeliveryReport dispatch and event defaults, but does not exercise the service-level +CMGR parsing path.
Minimal reproduction
Command run on clean main (23c53805bb63c0aaa7676033b92d108f32de7d81):
PYTHONPATH=. uv run --no-project --with pyserial-asyncio python - <<'PY'
import asyncio
from callstack.events.bus import EventBus
from callstack.events.types import _RawDeliveryReport, SMSDeliveryReportEvent
from callstack.protocol.executor import ATCommandExecutor
from callstack.protocol.urc import URCDispatcher
from callstack.sms.service import SMSService
from callstack.transport.mock import MockTransport
async def main():
bus = EventBus()
transport = MockTransport()
executor = ATCommandExecutor(transport, URCDispatcher(bus))
service = SMSService(executor, bus)
async with bus.stream(SMSDeliveryReportEvent) as stream:
# Text-mode status-report shape: stat, fo, mr, recipient, toa, sent ts, done ts, status.
transport.feed('+CMGR: "REC READ",6,"+12025550123",145,"24/12/25,14:30:00+04","24/12/25,14:30:05+04",0', 'OK', 'OK')
await service._on_delivery_report(_RawDeliveryReport(storage='SM', index=5))
event = await stream.next(timeout=1.0)
print({'event_reference': event.reference, 'event_recipient': event.recipient, 'event_status': event.status})
asyncio.run(main())
PY
Observed output:
{'event_reference': 0, 'event_recipient': '6', 'event_status': 'delivered'}
Expected behavior
For a text-mode status report containing message reference 6 and a recipient address, Callstack should emit an SMSDeliveryReportEvent with reference=6, the recipient address in recipient, and the parsed status.
Actual behavior
The message reference is misreported as the recipient, and the event reference remains the default 0.
Suggested fix direction
Add a dedicated delivery-report parser instead of naive split(",") parsing. It should handle quoted timestamps with embedded commas, text-mode status-report field order, and populate both reference and recipient. Then wire the parsed reference into SMSDeliveryReportEvent(reference=...) and future HTTP/store surfaces.
Acceptance criteria
- A service-level test feeds a representative
+CDSI/+CMGR status report and observes SMSDeliveryReportEvent(reference=<mr>, recipient=<address>, status="delivered").
- Pending/failure status-code ranges still map to
pending/failed.
- Quoted timestamps with embedded commas do not shift field indexes.
- Existing delivery-report tests and full suite continue to pass.
Verification gates
git diff --check
PYTHONPATH=. uv run --no-project --with pytest --with pytest-asyncio --with pytest-aiohttp --with pyserial-asyncio --with aiosqlite pytest tests/ -q
Duplicate search performed
No existing issue/PR was found with:
delivery report reference SMSDeliveryReportEvent reference in:title,body
CDSI CMGR reference delivery report correlation in:title,body
- PR search
delivery report reference SMSDeliveryReportEvent
Related but not duplicate: #19 is about backing HTTP SMS/delivery-report listings with SMSStore; this issue is about parsing and event correlation before persistence/listing.
Summary
SMSService._on_delivery_report()assumes the second comma-separated field in a+CMGRstatus-report response is the recipient. For text-mode status reports that include a message reference before the recipient, it emitsrecipient="6"and leavesreference=0, so delivery reports cannot be correlated back to the sent SMS reference.Affected source
callstack/sms/service.py:229-258line.split(",")on a quoted modem response.recipient = parts[1].strip().strip('"').SMSDeliveryReportEvent.referencefield even thoughevents/types.py:70-74defines it.tests/test_delivery_reports.pyverifies_RawDeliveryReportdispatch and event defaults, but does not exercise the service-level+CMGRparsing path.Minimal reproduction
Command run on clean
main(23c53805bb63c0aaa7676033b92d108f32de7d81):Observed output:
Expected behavior
For a text-mode status report containing message reference
6and a recipient address, Callstack should emit anSMSDeliveryReportEventwithreference=6, the recipient address inrecipient, and the parsed status.Actual behavior
The message reference is misreported as the recipient, and the event reference remains the default
0.Suggested fix direction
Add a dedicated delivery-report parser instead of naive
split(",")parsing. It should handle quoted timestamps with embedded commas, text-mode status-report field order, and populate bothreferenceandrecipient. Then wire the parsed reference intoSMSDeliveryReportEvent(reference=...)and future HTTP/store surfaces.Acceptance criteria
+CDSI/+CMGRstatus report and observesSMSDeliveryReportEvent(reference=<mr>, recipient=<address>, status="delivered").pending/failed.Verification gates
Duplicate search performed
No existing issue/PR was found with:
delivery report reference SMSDeliveryReportEvent reference in:title,bodyCDSI CMGR reference delivery report correlation in:title,bodydelivery report reference SMSDeliveryReportEventRelated but not duplicate: #19 is about backing HTTP SMS/delivery-report listings with
SMSStore; this issue is about parsing and event correlation before persistence/listing.