Send email with C# / .NET over SMTP (MailKit)
C# SMTP example with MailKit (the .NET-recommended library) using STARTTLS on 587 or SSL on 465, authentication, HTML body, attachments and async sending; plus the legacy System.Net.Mail.SmtpClient equivalent.
Install
dotnet add package MailKit
Complete example
using MailKit.Net.Smtp;
using MailKit.Security;
using MimeKit;
var host = Environment.GetEnvironmentVariable("SMTP_HOST") ?? "smtp.queensmtp.com";
var port = int.Parse(Environment.GetEnvironmentVariable("SMTP_PORT") ?? "587");
var user = Environment.GetEnvironmentVariable("SMTP_USER");
var pass = Environment.GetEnvironmentVariable("SMTP_PASS");
var message = new MimeMessage();
message.From.Add(new MailboxAddress("Your App", "hello@yourdomain.com"));
message.To.Add(MailboxAddress.Parse("customer@example.com"));
message.Subject = "Your receipt";
message.Body = new BodyBuilder
{
TextBody = "Thanks for your order #1042",
HtmlBody = "<h1>Thanks for your order</h1><p>#1042 is confirmed.</p>",
// Attachments = { "invoice-1042.pdf" }
}.ToMessageBody();
using var client = new SmtpClient();
client.Timeout = 20000;
await client.ConnectAsync(host, port,
port == 465 ? SecureSocketOptions.SslOnConnect : SecureSocketOptions.StartTls);
await client.AuthenticateAsync(user, pass);
await client.SendAsync(message);
await client.DisconnectAsync(true);
// legacy System.Net.Mail (obsolete in .NET, still common):
// using var smtp = new System.Net.Mail.SmtpClient(host, 587) { EnableSsl = true,
// Credentials = new System.Net.NetworkCredential(user, pass) };
// smtp.Send("hello@yourdomain.com", "customer@example.com", "Your receipt", "Thanks");What to know
- Microsoft marks System.Net.Mail.SmtpClient as not recommended (no modern auth, no async); MailKit is the supported path.
- SecureSocketOptions.StartTls for 587/2525, SslOnConnect for 465 — EnableSsl=true on the old client means STARTTLS and does NOT work on 465.
- Office 365 with basic auth disabled needs OAuth2 (MailKit supports SaslMechanismOAuth2); a relay avoids that entirely.
Same code, different provider
Only the host, port and credentials change. The rules per provider are on the SMTP settings hub.
| Provider | Host | Port | Username | Password | Note |
|---|---|---|---|---|---|
| QueenSMTP | smtp.queensmtp.com | 587 (STARTTLS) / 465 (SSL) / 2525 | SMTP username from the dashboard | SMTP password | $5/year + $0.10 per 1,000; 100 free/day |
| Gmail | smtp.gmail.com | 587 / 465 | you@gmail.com | App Password | 500/day, From must be the account |
| Amazon SES | email-smtp.<region>.amazonaws.com | 587 / 465 / 2587 | SES SMTP username | SES SMTP password | sandbox 200/day until approved |
| Office 365 | smtp.office365.com | 587 | user@yourdomain.com | mailbox password | SMTP AUTH must be enabled; 30/min |
| SendGrid | smtp.sendgrid.net | 587 / 465 / 2525 | apikey | API key | no free plan since 2025 |
Credentials for the example above
Create a free account, verify your sending domain (SPF + DKIM shown in the dashboard), add an SMTP credential, and paste it into the code. 100 emails a day free; $5/year plus $0.10 per 1,000 after that. Prefer HTTPS? The same account has a REST email API.
Get SMTP credentials Test your settings firstOther languages and frameworks
C# / .NET SMTP — questions
Credentials were not sent or basic auth is disabled on the tenant (Office 365). Check EnableSsl/StartTls, the credential object, and SMTP AUTH on the mailbox.
Related Guides
Continue learning with these related articles