MailSharp / MailSharp.MailClient / Services / SmtpService.cs
Code · 47 lines · 1551 bytes
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47using MailKit.Net.Smtp;
using MailSharp.MailClient.Models;
using MimeKit;
using System.Diagnostics;

namespace MailSharp.MailClient.Services;

public interface ISmtpService
{
	Task SendAsync(Account account, string password, MimeMessage message, CancellationToken ct = default);
}

public class SmtpService(ILogger<SmtpService> logger) : ISmtpService
{
	public async Task SendAsync(Account account, string password, MimeMessage message, CancellationToken ct = default)
	{
		using var scope = logger.BeginScope(new Dictionary<string, object?>
		{
			["accountId"] = account.Id,
			["to"] = message.To.ToString()
		});
		var sw = Stopwatch.StartNew();

		using var client = new SmtpClient();
		var secureSocket = account.SmtpSecurity switch
		{
			SecurityMode.SslTls => MailKit.Security.SecureSocketOptions.SslOnConnect,
			SecurityMode.StartTls => MailKit.Security.SecureSocketOptions.StartTls,
			_ => MailKit.Security.SecureSocketOptions.None
		};

		try
		{
			await client.ConnectAsync(account.SmtpHost, account.SmtpPort, secureSocket, ct);
			await client.AuthenticateAsync(account.Username, password, ct);
			await client.SendAsync(message, ct);
			await client.DisconnectAsync(true, ct);

			logger.LogInformation("Sent message {Subject} for account {AccountId} in {DurationMs}ms", message.Subject, account.Id, sw.ElapsedMilliseconds);
		}
		catch (Exception ex)
		{
			logger.LogError(ex, "Failed to send message {Subject} for account {AccountId} after {DurationMs}ms", message.Subject, account.Id, sw.ElapsedMilliseconds);
			throw;
		}
	}
}