✅ FREE Outbound SMS via email-to-SMS gateways
✅ No monthly fees or per-message costs
✅ Works with any email service (SendGrid, AWS SES, Gmail)
✅ Multiple inbound SMS solutions for true 2-way communication
Your App → Email Service → Carrier Gateway → User's Phone
Example:
Send email to: 5551234567@txt.att.net
User receives: "Your verification code is: 123456"
- Go to SendGrid.com
- Sign up for free (100 emails/day forever)
- Verify your account and get API key
# Add to your .env.local file
SENDGRID_API_KEY=your_sendgrid_api_key_here
EMAIL_FROM=noreply@yourdomain.com
# Remove Twilio variables to force email-to-SMS only
# TWILIO_ACCOUNT_SID= # commented out
# TWILIO_AUTH_TOKEN= # commented out# Test the email-to-SMS system
node scripts/test-email-to-sms.js
# Test with your app
curl -X POST http://localhost:3001/api/auth/send-verification \
-H "Content-Type: application/json" \
-d '{"phoneNumber": "+15551234567"}'| Carrier | SMS Gateway | Status |
|---|---|---|
| AT&T | @txt.att.net | ✅ Active |
| Verizon | @vtext.com | ✅ Active |
| T-Mobile | @tmomail.net | ✅ Active |
| Sprint | @messaging.sprintpcs.com | ✅ Active |
| Boost | @sms.myboostmobile.com | ✅ Active |
| Cricket | @sms.cricketwireless.net | ✅ Active |
| Metro | @mymetropcs.com | ✅ Active |
| Google Fi | @msg.fi.google.com | ✅ Active |
Since email-to-SMS is outbound only, here are solutions for inbound SMS:
// For development/testing only
const WEBHOOK_URL = 'https://webhook.site/your-unique-url';
// Users can send replies to any number, you monitor webhook
// Not for production, but great for testing// Keep one Twilio number ONLY for receiving
// Cost: ~$1/month for number + $0.01 per inbound SMS
// In your .env.local:
TWILIO_WEBHOOK_NUMBER=+1234567890 // Only for receiving
INBOUND_SMS_WEBHOOK_URL=https://yourdomain.com/api/sms/inbound// Telnyx charges less than Twilio
// Number: ~$0.50/month + $0.004 per inbound SMS
TELNYX_API_KEY=your_telnyx_key
TELNYX_PHONE_NUMBER=+1234567890// Some carriers forward SMS replies to email
// Very limited - depends on user's carrier
// AT&T and Verizon sometimes support this// Instead of SMS replies, use QR codes
// Users scan QR → web form → instant response
// 100% free, more reliable than SMS// Outbound only - perfect for verification codes
await sendVerificationSMS(phoneNumber, code);
// ✅ FREE, ❌ No inbound// Outbound: Free email-to-SMS
await sendVerificationSMS(phoneNumber, code);
// Inbound: Minimal Twilio webhook
// POST /api/sms/inbound
export async function POST(req: Request) {
const { From, Body } = await req.json();
console.log(`SMS from ${From}: ${Body}`);
// Handle user replies
}// Send SMS with QR code
const qrUrl = `https://yourdomain.com/respond/${sessionId}`;
await sendSMS(phone, `Verify: ${code}. Or scan: ${qrUrl}`);
// User scans QR → instant web form┌─────────────────┐ ┌──────────────────┐ ┌─────────────────┐
│ Your App │────│ Email Service │────│ Carrier SMS │
│ │ │ (SendGrid) │ │ Gateway │
└─────────────────┘ └──────────────────┘ └─────────────────┘
│ ▲
│ ┌──────────────────┐ │
└──────────────│ Twilio Webhook │───────────┘
│ (Inbound Only) │
└──────────────────┘
Outbound: 100% Free via Email-to-SMS
Inbound: ~$1/month via Twilio webhook
| Solution | Setup Cost | Monthly Cost | Per SMS |
|---|---|---|---|
| Pure Email-to-SMS | Free | Free | Free |
| Hybrid (Email + Twilio) | Free | ~$1 | $0.01 inbound only |
| Full Twilio | Free | ~$1 | $0.01 each way |
# Test real phone numbers with your carrier
curl -X POST http://localhost:3001/api/auth/send-verification \
-H "Content-Type: application/json" \
-d '{"phoneNumber": "+1YOUR_REAL_NUMBER"}'
# Check your phone for SMS!// Force specific carrier testing
await sendSmsViaEmail('+15551234567', 'Test message', 'att');
await sendSmsViaEmail('+15551234567', 'Test message', 'verizon');
await sendSmsViaEmail('+15551234567', 'Test message', 'tmobile');async function sendSMSReliably(phoneNumber: string, message: string) {
const carriers = ['att', 'verizon', 'tmobile', 'sprint'];
const promises = carriers.map(carrier =>
sendSmsViaEmail(phoneNumber, message, carrier)
);
// Send to all carriers, user gets it once
await Promise.all(promises);
}// Add user carrier selection in your UI
const CarrierSelector = () => (
<select name="carrier">
<option value="att">AT&T</option>
<option value="verizon">Verizon</option>
<option value="tmobile">T-Mobile</option>
{/* ... */}
</select>
);async function sendSMSWithFallbacks(phone: string, message: string) {
// Try auto-detection first
let result = await sendSmsViaEmail(phone, message);
if (!result.success) {
// Try major carriers
for (const carrier of ['att', 'verizon', 'tmobile']) {
result = await sendSmsViaEmail(phone, message, carrier);
if (result.success) break;
}
}
return result;
}- Delivery Time: 1-30 seconds (vs instant with Twilio)
- Success Rate: ~85-95% (vs 99%+ with Twilio)
- Carrier Blocking: Some carriers may block automated emails
- Rate Limits: Varies by carrier and email service
- International: Limited to supported carriers
- SendGrid account verified and API key added
- EMAIL_FROM domain verified with SendGrid
- Tested with real phone numbers on different carriers
- Inbound SMS solution chosen and implemented
- Error handling and retry logic added
- Rate limiting implemented
- Monitoring and alerts set up
Your free SMS system is now operational! You can:
✅ Send unlimited verification codes for FREE
✅ Handle user registration and login
✅ Add inbound SMS with minimal cost (~$1/month)
✅ Scale without per-message charges
Next steps:
- Test with your real phone number
- Choose an inbound SMS solution
- Deploy and enjoy free messaging! 🎉