If you searched for `ruby send email smtp`, the production-safe path is:

1. use `Net::SMTP` with explicit auth/TLS settings
2. externalize SMTP config per environment
3. assert real inbox outcomes in tests
4. run deliverability diagnostics before release

![send and read email in ruby](/assets/ruby-smtp-read-email.jpg)

## Quick setup with Net::SMTP

```ruby
require 'net/smtp'

message = <<~MESSAGE
  From: no-reply@example.com
  To: user@example.com
  Subject: Welcome

  Your account is ready.
MESSAGE

Net::SMTP.start(
  'smtp.example.com',
  587,
  'example.com',
  'smtp-user',
  'smtp-password',
  :plain
) do |smtp|
  smtp.send_message(message, 'no-reply@example.com', 'user@example.com')
end
```

## SMTP settings Ruby teams should lock down

Define and validate:

- SMTP host and port
- authentication mode (`:plain`, `:login`, or provider-required mode)
- TLS/STARTTLS transport expectations
- sender-domain alignment for SPF, DKIM, and DMARC
- timeout and retry behavior for transient failures

Related references:

- [SMTP authentication](/blog/smtp-authentication/)
- [STARTTLS vs SSL/TLS](/blog/starttls-ssl-tls/)
- [SMTP ports guide](/guides/what-are-smtp-ports/)

## Environment-driven Ruby SMTP configuration

```ruby
require 'net/smtp'

host = ENV.fetch('SMTP_HOST')
port = Integer(ENV.fetch('SMTP_PORT'))
user = ENV.fetch('SMTP_USERNAME')
pass = ENV.fetch('SMTP_PASSWORD')
from = ENV.fetch('SMTP_FROM_ADDRESS')

to = 'recipient@example.com'
message = <<~MESSAGE
  From: #{from}
  To: #{to}
  Subject: SMTP test

  This is a production-style SMTP send test.
MESSAGE

Net::SMTP.start(host, port, 'example.com', user, pass, :plain) do |smtp|
  smtp.send_message(message, from, to)
end
```

This keeps secrets out of code and makes staging/production parity easier.

## Common Ruby SMTP failures and fixes

### Authentication errors

Likely causes:

- invalid credentials
- wrong auth mode
- sender-domain policy mismatch

Fixes:

- verify credential source and rotation timing
- confirm auth mechanism expected by provider
- validate sender-domain authentication posture

### TLS/connection failures

Likely causes:

- wrong port/transport expectations
- blocked outbound network egress
- certificate or trust-chain mismatch

Fixes:

- confirm port and TLS requirements
- verify firewall/egress policy
- align transport mode with provider docs

### SMTP accepted but message not visible in inbox

Transport success is not the same as inbox placement.

Add diagnostics:

- [Email deliverability test](/testing/email-deliverability-test/)
- [Email spam checker](/tools/email-spam-checker/)

## Test Ruby SMTP workflows before release

Run deterministic inbox tests for:

- account verification flows
- password reset flows
- billing and receipt messages
- alert and support notifications

Recommended workflow pages:

- [Email Sandbox](/product/email-sandbox/)
- [Email integration testing](/product/email-integration-testing/)
- [Email webhooks](/guides/email-webhooks/)

## Ruby SMTP production checklist

1. Use env-driven SMTP host/port/auth configuration.
2. Validate sender-domain SPF/DKIM/DMARC alignment.
3. Add inbox-based assertions for release-critical paths.
4. Add retry and timeout controls for transient failures.
5. Re-test after DNS, template, or provider changes.

## FAQ

### Can Ruby send SMTP email without external gems?

Yes. `Net::SMTP` is part of Ruby's standard library and is enough for many transactional workflows.

### Which Ruby SMTP auth mode should I use?

Use the mode your provider requires. `:plain` and `:login` are common, but you should verify this in provider docs.

### How do I validate Ruby SMTP reliably in CI?

Use isolated inboxes and deterministic receive assertions, not just successful SMTP transport calls.

## Next steps

- [SMTP and IMAP guide](/guides/smtp-imap/)
- [Deliverability testing workflow](/testing/email-deliverability-test/)
- [Email Sandbox setup](/product/email-sandbox/)
