private async Task SendEhlo(SmtpSender sender, Connection connection, CancellationToken cancellationToken) { sender.RequestText = $"{SmtpCommandNames.EHLO} {ClientHostname}"; await connection.WriteLineAsync(sender.RequestText, cancellationToken).ConfigureAwait(false); do { sender.ReplyText = await connection.ReadLineAsync(cancellationToken).ConfigureAwait(false); }while (!sender.IsReplyOk); sender.ValidateReply(); }
public ConnectionAuth(Connection connection, SmtpSender sender, NetworkCredential credentials) { _connection = connection; _sender = sender; _credentials = credentials; }
/// <summary> /// Sends an array of email messages using a session state object. /// Credentials, Enable SSL and Client Hostname are NOT taken from the state object but /// rather from the properties of this class. /// </summary> /// <param name="sessionStates">The session states.</param> /// <param name="sessionId">The session identifier.</param> /// <param name="callback">The callback.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns> /// A task that represents the asynchronous of send email operation. /// </returns> /// <exception cref="ArgumentNullException">sessionStates.</exception> /// <exception cref="SecurityException">Could not upgrade the channel to SSL.</exception> /// <exception cref="SmtpException">Defines an SMTP Exceptions class.</exception> public async Task SendMailAsync( IEnumerable <SmtpSessionState> sessionStates, string?sessionId = null, RemoteCertificateValidationCallback?callback = null, CancellationToken cancellationToken = default) { if (sessionStates == null) { throw new ArgumentNullException(nameof(sessionStates)); } using var tcpClient = new TcpClient(); await tcpClient.ConnectAsync(Host, Port, cancellationToken).ConfigureAwait(false); using var connection = new Connection(tcpClient, Encoding.UTF8, "\r\n", true, 1000); var sender = new SmtpSender(sessionId); try { // Read the greeting message sender.ReplyText = await connection.ReadLineAsync(cancellationToken).ConfigureAwait(false); // EHLO 1 await SendEhlo(sender, connection, cancellationToken).ConfigureAwait(false); // STARTTLS if (EnableSsl) { sender.RequestText = $"{SmtpCommandNames.STARTTLS}"; await connection.WriteLineAsync(sender.RequestText, cancellationToken).ConfigureAwait(false); sender.ReplyText = await connection.ReadLineAsync(cancellationToken).ConfigureAwait(false); sender.ValidateReply(); if (await connection.UpgradeToSecureAsClientAsync(callback: callback).ConfigureAwait(false) == false) { throw new SecurityException("Could not upgrade the channel to SSL."); } } // EHLO 2 await SendEhlo(sender, connection, cancellationToken).ConfigureAwait(false); // AUTH if (Credentials != null) { var auth = new ConnectionAuth(connection, sender, Credentials); await auth.AuthenticateAsync(cancellationToken).ConfigureAwait(false); } foreach (var sessionState in sessionStates) { { // MAIL FROM sender.RequestText = $"{SmtpCommandNames.MAIL} FROM:<{sessionState.SenderAddress}>"; await connection.WriteLineAsync(sender.RequestText, cancellationToken).ConfigureAwait(false); sender.ReplyText = await connection.ReadLineAsync(cancellationToken).ConfigureAwait(false); sender.ValidateReply(); } // RCPT TO foreach (var recipient in sessionState.Recipients) { sender.RequestText = $"{SmtpCommandNames.RCPT} TO:<{recipient}>"; await connection.WriteLineAsync(sender.RequestText, cancellationToken).ConfigureAwait(false); sender.ReplyText = await connection.ReadLineAsync(cancellationToken).ConfigureAwait(false); sender.ValidateReply(); } { // DATA sender.RequestText = $"{SmtpCommandNames.DATA}"; await connection.WriteLineAsync(sender.RequestText, cancellationToken).ConfigureAwait(false); sender.ReplyText = await connection.ReadLineAsync(cancellationToken).ConfigureAwait(false); sender.ValidateReply(); } { // CONTENT var dataTerminator = sessionState.DataBuffer .Skip(sessionState.DataBuffer.Count - 5) .ToText(); sender.RequestText = $"Buffer ({sessionState.DataBuffer.Count} bytes)"; await connection.WriteDataAsync(sessionState.DataBuffer.ToArray(), true, cancellationToken).ConfigureAwait(false); if (!dataTerminator.EndsWith(SmtpDefinitions.SmtpDataCommandTerminator, StringComparison.OrdinalIgnoreCase)) { await connection.WriteTextAsync(SmtpDefinitions.SmtpDataCommandTerminator, cancellationToken).ConfigureAwait(false); } sender.ReplyText = await connection.ReadLineAsync(cancellationToken).ConfigureAwait(false); sender.ValidateReply(); } } { // QUIT sender.RequestText = $"{SmtpCommandNames.QUIT}"; await connection.WriteLineAsync(sender.RequestText, cancellationToken).ConfigureAwait(false); sender.ReplyText = await connection.ReadLineAsync(cancellationToken).ConfigureAwait(false); sender.ValidateReply(); } } catch (Exception ex) { throw new SmtpException($"Could not send email - Session ID {sessionId}. {ex.Message}\r\n Last Request: {sender.RequestText}\r\n Last Reply: {sender.ReplyText}"); } }