A lightweight SMTP-to-SMS gateway that converts incoming emails to SMS messages. Send SMS by simply sending an email to phonenumber@yourdomain.com.
- SMTP Server: Receives emails on port 2525
- SMS Providers: Support for Twilio, AWS SNS, and custom webhooks
- Web Interface: Modern Bootstrap 5 dashboard with HTTPS support
- Security: CSP, HSTS, X-Frame-Options, XSS-Protection, and more
- Phone Management: Allowlist for restricting which numbers receive SMS
- Message Logging: Dashboard to view sent messages
- Self-signed SSL: Auto-generated certificates for HTTPS
- Mobile Responsive: Hamburger menu for mobile devices
| Desktop | Tablet | Mobile |
|---|---|---|
![]() |
![]() |
![]() |
| Desktop | Tablet | Mobile |
|---|---|---|
![]() |
![]() |
![]() |
| Desktop | Tablet | Mobile |
|---|---|---|
![]() |
![]() |
![]() |
| SMTP Server | Phone Numbers |
|---|---|
![]() |
![]() |
| Gateway | Authentication |
|---|---|
![]() |
![]() |
| Security |
|---|
![]() |
- Node.js 18 or higher
- npm
- Twilio account (or AWS SNS or custom webhook)
git clone https://github.com/jsmeyers/smtp-to-sms.git
cd smtp-to-smsnpm installCopy the example configuration files:
cp config/gateway.json.example config/gateway.json
cp config/web.json.example config/web.json
cp config/smtp.json.example config/smtp.json
cp config/phones.json.example config/phones.jsonEdit the configuration files with your settings:
# Configure SMS gateway (Twilio, SNS, or webhook)
nano config/gateway.json
# Configure web interface
nano config/web.jsonnpm startThe server will start:
- SMTP Server: Port 2525
- HTTP Web Interface: Port 8080 (redirects to HTTPS)
- HTTPS Web Interface: Port 8443
- Open
https://localhost:8443(or your server's IP) - Accept the self-signed certificate warning
- Create an admin account
- Configure your SMS gateway settings
Edit config/gateway.json:
{
"type": "twilio",
"twilio": {
"accountSid": "YOUR_ACCOUNT_SID",
"authToken": "YOUR_AUTH_TOKEN",
"fromNumber": "+1234567890"
}
}{
"type": "sns",
"sns": {
"accessKeyId": "YOUR_ACCESS_KEY",
"secretAccessKey": "YOUR_SECRET_KEY",
"region": "us-east-1"
}
}{
"type": "webhook",
"webhook": {
"url": "https://your-webhook.com/sms",
"method": "POST",
"headers": {},
"phoneField": "phone",
"messageField": "message"
}
}Edit config/smtp.json:
{
"listenIp": "0.0.0.0",
"port": 2525,
"ipMode": "all",
"allowedIps": [],
"domain": "localhost"
}ipMode:all,subnet, orlistallowedIps: Array of IPs whenipModeislist
Edit config/web.json:
{
"port": 8080,
"httpsPort": 8443,
"forceHttps": true,
"sslCN": "localhost",
"username": "",
"passwordHash": ""
}forceHttps: Redirect HTTP to HTTPSsslCN: Common Name for self-signed certificate
Edit config/phones.json:
{
"mode": "all",
"numbers": []
}mode:all(accept all) orlist(whitelist only)numbers: Array of allowed phone numbers (when mode islist)
Send an email to phonenumber@yourdomain.com:
To: 15551234567@yourdomain.com
Subject: Test Message
This is the SMS body text.
The gateway will:
- Extract the phone number from the email address
- Check if the phone number is allowed
- Send the SMS via your configured provider
- Log the result in the web dashboard
| Format | Phone Extracted |
|---|---|
15551234567@domain.com |
15551234567 |
5551234567@domain.com |
15551234567 (adds 1) |
+15551234567@domain.com |
15551234567 |
Access the dashboard at https://your-server:8443:
- Dashboard: Overview of message activity
- Messages: View sent message history
- Settings: Configure SMTP, phone numbers, gateway, authentication
- Security: Configure HTTPS and security settings
The web interface requires authentication. On first run, you'll be prompted to create an admin account.
The gateway auto-generates self-signed SSL certificates stored in ssl/. For production:
- Replace
ssl/server.crtandssl/server.keywith certificates from a trusted CA - Or use a reverse proxy (nginx, Apache) for TLS termination
The gateway implements OWASP-recommended security headers:
| Header | Value |
|---|---|
| Content-Security-Policy | Configured for self-hosted resources |
| Strict-Transport-Security | max-age=31536000; includeSubDomains; preload |
| X-Frame-Options | DENY |
| X-XSS-Protection | 0 |
| X-Content-Type-Options | nosniff |
| Referrer-Policy | strict-origin-when-cross-origin |
| Cross-Origin policies | Enabled for HTTPS |
Restrict SMTP access by IP:
// Allow only specific IPs
{
"ipMode": "list",
"allowedIps": ["192.168.1.100", "10.0.0.0/24"]
}
// Allow local subnet only
{
"ipMode": "subnet"
}The server includes detailed logging. Check logs for:
- SMTP connections
- Email parsing
- Phone number extraction
- SMS sending attempts
- Twilio responses
Email not being processed:
- Ensure SMTP client sends proper
DATAcommand - Email must end with
.on its own line - Check server logs for parsing errors
SMS not sent:
- Verify Twilio credentials
- Check phone number format (10 or 11 digits)
- Verify phone is in the allowed list (if using list mode)
HTTPS certificate warning:
- Self-signed certificates will show browser warnings
- For production, use trusted certificates
# Connect to SMTP server
telnet localhost 2525
# Send test email
HELO localhost
MAIL FROM:<test@example.com>
RCPT TO:<15551234567@localhost>
DATA
Subject: Test
This is a test message.
.
QUITsmtp-to-sms/
├── config/ # Configuration files
│ ├── gateway.json # SMS provider settings
│ ├── web.json # Web interface settings
│ ├── smtp.json # SMTP server settings
│ └── phones.json # Phone number allowlist
├── src/
│ ├── index.js # Main entry point
│ ├── smtp-server.js # SMTP server
│ ├── sms/ # SMS providers
│ ├── web/ # Web interface
│ └── config.js # Configuration loader
├── views/ # EJS templates
├── public/ # Static assets
│ ├── css/
│ ├── js/
│ └── vendor/ # Bootstrap
├── ssl/ # SSL certificates (generated)
├── data/ # Message logs
└── package.json
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.













