SMTP authentication is the process by which your application proves its identity to the MigoSMTP server before it is permitted to send email. There are several authentication mechanisms available — this article explains each one, compares their security properties, and tells you which to use in which circumstance.
Why SMTP Authentication Is Required
MigoSMTP requires every connection to authenticate before accepting email for delivery. This prevents unauthorised use of the relay server and ensures that every email sent can be attributed to a specific account — enabling rate limiting, abuse detection, and per-account reporting.
Authentication happens during the SMTP session immediately after the TLS connection is established, using the AUTH command followed by the chosen mechanism name.
Supported Authentication Mechanisms
| Mechanism | How It Works | Security Level | Use This? |
|---|---|---|---|
| LOGIN | Sends the username and password as separate Base64-encoded strings in a challenge-response exchange | Safe over TLS; credentials visible if TLS is stripped | ✓ Recommended — most widely supported |
| PLAIN | Sends the authentication identity, username, and password as a single Base64-encoded string | Safe over TLS; similar risk to LOGIN if TLS not enforced | ✓ Acceptable — simpler than LOGIN |
| CRAM-MD5 | Challenge-response — server sends a random challenge; client hashes it with the password using HMAC-MD5 and returns the hash. Password never transmitted directly. | Does not expose password even if intercepted | Legacy — supported but not recommended for new integrations |
| OAUTH2 | Token-based authentication — no password transmitted; client presents a valid OAuth 2.0 bearer token | Highest security — no password exposure risk | Not currently supported by MigoSMTP SMTP relay |
LOGIN Mechanism — How It Works Step by Step
The LOGIN mechanism is the most commonly used and is what most libraries default to when you specify username and password authentication:
Client: AUTH LOGIN Server: 334 VXNlcm5hbWU6 ← Base64 for "Username:" Client: [Base64-encoded username] Server: 334 UGFzc3dvcmQ6 ← Base64 for "Password:" Client: [Base64-encoded password] Server: 235 2.7.0 Authentication successful
PLAIN Mechanism — How It Works Step by Step
PLAIN sends all three values (identity, username, password) in a single step separated by null bytes, Base64-encoded:
Client: AUTH PLAIN [Base64({identity} {username} {password})]
Server: 235 2.7.0 Authentication successful
# Example encoding in Python:
import base64
auth_string = " " + "your_smtp_username" + " " + "your_smtp_password"
encoded = base64.b64encode(auth_string.encode()).decode()
# → AUTH PLAIN [encoded_value]
CRAM-MD5 Mechanism — How It Works Step by Step
Client: AUTH CRAM-MD5
Server: 334 [Base64-encoded challenge] ← e.g. <1234.567@smtp.migosmtp.com>
Client: [Base64({username} {HMAC-MD5(challenge, password)})]
Server: 235 2.7.0 Authentication successful
Which Mechanism Is Used by Common Libraries?
| Library / Framework | Default Auth Mechanism | How to Specify LOGIN |
|---|---|---|
| PHPMailer | AUTO (negotiates best available) | $mail->AuthType = 'LOGIN'; |
| Python smtplib | PLAIN | server.login(user, pass) uses PLAIN by default |
| Nodemailer | AUTO (LOGIN or PLAIN) | auth: { type: 'login', user, pass } |
| Laravel (Symfony Mailer) | AUTO | Laravel auto-negotiates based on server capabilities |
| Java (jakarta.mail) | PLAIN | smtp.PlainAuth("", user, pass, host) |
| Ruby net/smtp | PLAIN | SMTP.start(..., :login) for LOGIN mechanism |
Why LOGIN and PLAIN Are Safe Over TLS
LOGIN and PLAIN transmit credentials in Base64 encoding, which is trivially reversible. However, this is safe in practice because:
- All MigoSMTP connections require TLS (STARTTLS or implicit SSL).
- Once the TLS layer is established, all data — including the AUTH exchange — is encrypted end-to-end.
- An attacker intercepting the network traffic would see only encrypted bytes, not the Base64-encoded credentials.
- MigoSMTP enforces STARTTLS before accepting authentication — connections that do not upgrade to TLS are rejected before the AUTH phase.