SmsForwarder is an Android app that monitors incoming SMS and app notifications on your phone and forwards them to external destinations (email, webhook, etc.) based on rules you define.
In the TPS pipeline, SmsForwarder plays one role: forward bank transaction SMS and cashback notifications to your Gmail inbox as emails, so TPS can pick them up alongside regular bank emails and parse them into Cashew transactions.
Bank transaction emails are often delayed or missing for certain transaction types (UPI, debit card POS, transfers). SMS arrives instantly. By forwarding SMS to email, TPS gets a unified inbox of both email and SMS-sourced transactions with zero changes to its email-based processing pipeline.
Phone receives SMS/Notification
|
v
SmsForwarder intercepts it
|
v
Matches against forwarding rules (sender + content regex)
|
+---+---+
| |
v v
[Transaction Rule] [Catch-All Rule]
| |
v v
Email Sender Localhost Sender (no-op)
| |
v v
Gmail -> TPS Logged locally for review
| Setting | Value | Why |
|---|---|---|
| Forward SMS | ON | Main switch for SMS rules |
| Forward App Notify | ON | Main switch for APP notification rules |
| Forward Calls | OFF | Not needed for TPS |
| Retry Interval | 1 (or higher) | Auto-retry on network failure |
| Filter Duplicate Messages | 0 (disabled) | TPS handles deduplication |
Global Custom Template:
Transaction SMS :
{{MSG}}
Received : {{RECEIVE_TIME}}
{{MSG}}= SMS body or notification body{{RECEIVE_TIME}}= timestamp when the message was received- TPS uses the
Received :line to extract the transaction timestamp - Set date format to
DD/MM/YY HH:mm:ssin General Settings to match TPS'sDefaultRegexMap.dateRegex
You need two senders:
Sender 1: Email (for transaction rules)
| Field | Value |
|---|---|
| Nickname | TPS Email |
| Account | Your sender Gmail address |
| Password | Gmail App Password (generate here, requires 2FA) |
| E2EE | Plain |
| Recipients | The Gmail address TPS monitors |
| Email Title | Transaction SMS [{{RECEIVE_TIME}}] |
TPS identifies SMS-sourced emails by checking if the subject starts with Transaction SMS.
Sender 2: Webhook/Localhost (for catch-all logging)
| Field | Value |
|---|---|
| Nickname | Rejected SMS Log |
| Webhook | http://127.0.0.1:5000 |
This intentionally fails (nothing is listening). The message gets logged locally in SmsForwarder's Logs so you can review unmatched SMS patterns periodically.
Rules define which messages get forwarded and to which sender.
SMS Rule Example -- Forward transaction SMS from your bank:
AND IS PHONE_NUM CONTAIN MYBANK
AND IS MSG_CONTENT REGEX (?i)^(?!.*\bOTP\b).*(?:debited|credited|withdrawn)
Sender = TPS Email
This forwards SMS where sender contains "MYBANK" and body has a transaction keyword but not "OTP".
APP Notification Rule Example -- Forward cashback notifications:
AND IS PACKAGE_NAME EQUALS com.example.paymentapp
AND IS INFORM_TITLE REGEX (?i)cashback|reward
Sender = TPS Email
Catch-All Rules (Recommended)
Create catch-all rules placed after all transaction rules:
- SMS Catch-All: Field = All, Sender =
Rejected SMS Log - APP Catch-All: Field = All, Sender =
Rejected SMS Log
SmsForwarder evaluates rules top-to-bottom; first match wins. Unmatched messages fall through to the catch-all and get logged locally.
Every intercepted message appears here with its forwarding status (Success/Failed/Skipped). Check catch-all logs periodically to discover new transaction patterns you should add rules for.
When using the Multiple field type, each line follows:
<conjunction> <sure> <field> <check> <value>
| Part | Values | Purpose |
|---|---|---|
| conjunction | AND, OR |
Logical connector |
| sure | IS, NOTIS |
Affirm or negate |
| field | PHONE_NUM, MSG_CONTENT, PACKAGE_NAME, INFORM_TITLE, INFORM_CONTENT |
What to match |
| check | EQUALS, CONTAIN, NOTCONTAIN, STARTWITH, ENDWITH, REGEX |
Comparison |
| value | (anything) | Match text/pattern |
Nesting with indentation:
- First line: no leading spaces
- Line with 1 leading space: child of previous (grouped together)
- Same indentation: sibling at the same level
Example with OR grouping:
AND IS PHONE_NUM CONTAIN BANKONE
OR IS PHONE_NUM CONTAIN BANKTWO
AND IS MSG_CONTENT REGEX (?i)^(?!.*\bOTP\b).*(?:debited|credited)
Reads as: (sender has "BANKONE" OR sender has "BANKTWO") AND body matches regex
| SMS | APP Notification | |
|---|---|---|
| Subject prefix | Must start with Transaction SMS |
Matched via emailSubjectToRuleIdMap |
| Rule lookup | smsRuleMap (body content match) |
emailRuleMap (subject match) |
| Date source | Received : line in body |
Received : line or email date |
- SmsForwarder: Add rule with
PHONE_NUM CONTAIN <BANK>+ transaction regex - userConfig: Add entry in
smsReferencePatternsfor message identification - userConfig: Add entry in
smsRuleMapwith regex for amount, account, merchant, etc. - Test: Re-forward an SMS from inbox and verify TPS parses it correctly
- SmsForwarder: Add rule with
PACKAGE_NAME EQUALS <package>+ title/content regex - SmsForwarder: Set a distinctive Email Title for the rule
- userConfig: Add subject mapping in
emailSubjectToRuleIdMap - userConfig: Add parsing rule in
emailRuleMap - Gmail: Add filter for the new subject pattern to the TPS label
- Test: Trigger the notification and verify end-to-end
| Permission | Purpose |
|---|---|
| Read SMS | Intercept incoming SMS |
| Notification Access | Read app notifications |
| Battery Optimization | Set to "Don't optimize" so Android doesn't kill it |
| Auto-start | Enable in phone settings (varies by manufacturer) |
| Problem | Fix |
|---|---|
| Rule says "malformed" | Check syntax: use EQUALS not IS for equality; no consecutive spaces; exactly 4 keywords per line |
| SMS not forwarding | Change rule to Any SIM; disable battery optimization; enable auto-start |
| Email test fails | Regenerate Gmail App Password; ensure 2FA is enabled |
| Duplicate emails | Tighten regex or rely on TPS deduplication |
| OTP messages forwarded | Add (?!.*\bOTP\b) negative lookahead to regex |
| Catch-all logs empty | Move catch-all to the bottom of the rule list |
Before SmsForwarder, TPS used the Automate app for SMS forwarding. Automate uses visual flow-based automation and works well for simple forwarding, but has some limitations:
- No built-in multi-condition rules (you need complex flow branches for sender + content filtering)
- No catch-all logging for discovering missed patterns
- No APP notification support (only SMS)
- Offline handling requires a separate "backup" flow that batches missed SMS and sends them later (this is what the
Txs/🛜label was for)
If you are already using Automate and it works for your setup, there is no need to switch. TPS processes the forwarded emails the same way regardless of which app sent them. The key requirement is that the email subject starts with Transaction SMS and the body follows the template format (Transaction SMS :\n<body>\nReceived : DD/MM/YY HH:mm:ss).
A starter Automate flow is included in the resources folder: Download .flo file
To set it up:
- Download and install Automate
- Import the
.flofile above - Authenticate Google Drive: create a flow with a single Google Drive block, tap the Google account field, and select your account
- Update the regex pattern in the flow to match your bank's SMS format
- Run and test
For new setups, we recommend SmsForwarder (documented above) for its rule flexibility, catch-all logging, and APP notification support.