/// <summary> /// Send the MAIL FROM command to the server using <paramref name="mailFrom"/> as parameter. /// </summary> /// <param name="mailFrom">Email address to use as parameter.</param> /// <param name="failedCallback">Action to call if command fails.</param> public async Task <bool> ExecMailFromAsync(MailAddress mailFrom, Action <string> failedCallback) { if (!base.Connected) { return(false); } _LastActive = DateTime.UtcNow; IsActive = true; await SmtpStream.WriteLineAsync("MAIL FROM: <" + (mailFrom == null ? string.Empty : mailFrom.Address) + ">" + (_DataTransportMime == SmtpTransportMIME._8BitUTF ? " BODY=8BITMIME" : string.Empty)); // If the remote MX doesn't support pipelining then wait and check the response. if (!_CanPipeline) { string response = await SmtpStream.ReadAllLinesAsync(); if (!response.StartsWith("250")) { failedCallback(response); } } _LastActive = DateTime.UtcNow; IsActive = false; return(true); }
/// <summary> /// Send the RCPT TO command to the server using <paramref name="rcptTo"/> as parameter. /// </summary> /// <param name="rcptTo">Email address to use as parameter.</param> /// <param name="failedCallback">Action to call if command fails.</param> public async Task <bool> ExecRcptToAsync(MailAddress rcptTo, Action <string> failedCallback) { if (!base.Connected) { return(false); } IsActive = true; _LastActive = DateTime.UtcNow; await SmtpStream.WriteLineAsync("RCPT TO: <" + rcptTo.Address + ">"); // If the remote MX doesn't support pipelining then wait and check the response. if (!_CanPipeline) { string response = await SmtpStream.ReadAllLinesAsync(); if (!response.StartsWith("250")) { failedCallback(response); } } _LastActive = DateTime.UtcNow; IsActive = false; return(true); }
/// <summary> /// Send the data to the server /// </summary> /// <param name="data">Data to send to the server</param> /// <param name="failedCallback">Action to call if fails to send.</param> private async Task <MantaOutboundClientSendResult> ExecDataAsync(string data) { await SmtpStream.WriteLineAsync("DATA"); string response = await SmtpStream.ReadAllLinesAsync(); // Data response or Mail From if pipelining // If the remote MX supports pipelining then we need to check the MAIL FROM and RCPT to responses. if (_CanPipeline) { // Check MAIL FROM OK. if (!response.StartsWith("250")) { await SmtpStream.ReadAllLinesAsync(); // RCPT TO await SmtpStream.ReadAllLinesAsync(); // DATA return(new MantaOutboundClientSendResult(MantaOutboundClientResult.RejectedByRemoteServer, response, _VirtualMta, _MXRecord)); } // Check RCPT TO OK. response = await SmtpStream.ReadAllLinesAsync(); if (!response.StartsWith("250")) { await SmtpStream.ReadAllLinesAsync(); // DATA return(new MantaOutboundClientSendResult(MantaOutboundClientResult.RejectedByRemoteServer, response, _VirtualMta, _MXRecord)); } // Get the Data Command response. response = await SmtpStream.ReadAllLinesAsync(); } if (!response.StartsWith("354")) { return(new MantaOutboundClientSendResult(MantaOutboundClientResult.RejectedByRemoteServer, response, _VirtualMta, _MXRecord)); } // Send the message data using the correct transport MIME SmtpStream.SetSmtpTransportMIME(_DataTransportMime); await SmtpStream.WriteAsync(data, false); await SmtpStream.WriteAsync(MtaParameters.NewLine + "." + MtaParameters.NewLine, false); // Data done so return to 7-Bit mode. SmtpStream.SetSmtpTransportMIME(SmtpTransportMIME._7BitASCII); response = await SmtpStream.ReadAllLinesAsync(); if (!response.StartsWith("250")) { return(new MantaOutboundClientSendResult(MantaOutboundClientResult.RejectedByRemoteServer, response, _VirtualMta, _MXRecord)); } _MessagesAccepted++; return(new MantaOutboundClientSendResult(MantaOutboundClientResult.Success, response, _VirtualMta, _MXRecord)); }
/// <summary> /// Say EHLO/HELO to the server. /// Will also check to see if 8BITMIME is supported. /// </summary> /// <param name="failedCallback">Action to call if hello fail.</param> private async Task <MantaOutboundClientSendResult> ExecHeloAsync() { // We have connected to the MX, Say EHLO. await SmtpStream.WriteLineAsync("EHLO " + _VirtualMta.Hostname); string response = await SmtpStream.ReadAllLinesAsync(); if (response.StartsWith("421")) { return(new MantaOutboundClientSendResult(MantaOutboundClientResult.ServiceNotAvalible, response, _VirtualMta, _MXRecord)); } try { if (!response.StartsWith("2")) { // If server didn't respond with a success code on hello then we should retry with HELO await SmtpStream.WriteLineAsync("HELO " + _VirtualMta.Hostname); response = await SmtpStream.ReadAllLinesAsync(); if (!response.StartsWith("250")) { TcpClient.Close(); return(new MantaOutboundClientSendResult(MantaOutboundClientResult.ServiceNotAvalible, response, _VirtualMta, _MXRecord)); } } else { // Server responded to EHLO // Check to see if it supports 8BITMIME if (response.IndexOf("8BITMIME", StringComparison.OrdinalIgnoreCase) > -1) { _DataTransportMime = SmtpTransportMIME._8BitUTF; } else { _DataTransportMime = SmtpTransportMIME._7BitASCII; } // Check to see if the server supports pipelining _CanPipeline = response.IndexOf("PIPELINING", StringComparison.OrdinalIgnoreCase) > -1; } } catch (IOException) { // Remote Endpoint Disconnected Mid HELO. return(new MantaOutboundClientSendResult(MantaOutboundClientResult.ServiceNotAvalible, response, _VirtualMta, _MXRecord)); } return(new MantaOutboundClientSendResult(MantaOutboundClientResult.Success, null, _VirtualMta, _MXRecord)); }
/// <summary> /// Send the RSET command to the server. /// </summary> public async Task <bool> ExecRsetAsync() { if (!base.Connected) { Logging.Debug("Cannot RSET connection has been closed."); throw new Exception(); } IsActive = true; await SmtpStream.WriteLineAsync("RSET"); await SmtpStream.ReadAllLinesAsync(); _LastActive = DateTime.UtcNow; IsActive = false; return(true); }
/// <summary> /// Send the RCPT TO command to the server using <paramref name="rcptTo"/> as parameter. /// </summary> /// <param name="rcptTo">Email address to use as parameter.</param> /// <param name="failedCallback">Action to call if command fails.</param> private async Task <MantaOutboundClientSendResult> ExecRcptToAsync(MailAddress rcptTo) { await SmtpStream.WriteLineAsync("RCPT TO: <" + rcptTo.Address + ">"); // If the remote MX doesn't support pipelining then wait and check the response. if (!_CanPipeline) { string response = await SmtpStream.ReadAllLinesAsync(); if (!response.StartsWith("250")) { return(new MantaOutboundClientSendResult(MantaOutboundClientResult.RejectedByRemoteServer, response, _VirtualMta, _MXRecord)); } } return(new MantaOutboundClientSendResult(MantaOutboundClientResult.Success, null, _VirtualMta, _MXRecord)); }
/// <summary> /// Send the RSET command to the server. /// </summary> private async Task <MantaOutboundClientSendResult> ExecRsetAsync() { if (!await SmtpStream.WriteLineAsync("RSET")) { throw new ObjectDisposedException("Connection"); } var response = await SmtpStream.ReadAllLinesAsync(); switch (response[0]) { case '2': return(new MantaOutboundClientSendResult(MantaOutboundClientResult.Success, response, _VirtualMta, _MXRecord)); case '4': case '5': default: return(new MantaOutboundClientSendResult(MantaOutboundClientResult.RejectedByRemoteServer, response, _VirtualMta, _MXRecord)); } }
/// <summary> /// Send the MAIL FROM command to the server using <paramref name="mailFrom"/> as parameter. /// </summary> /// <param name="mailFrom">Email address to use as parameter.</param> /// <param name="failedCallback">Action to call if command fails.</param> private async Task <MantaOutboundClientSendResult> ExecMailFromAsync(MailAddress mailFrom) { await SmtpStream.WriteLineAsync("MAIL FROM: <" + (mailFrom == null ? string.Empty : mailFrom.Address) + ">" + (_DataTransportMime == SmtpTransportMIME._8BitUTF ? " BODY=8BITMIME" : string.Empty)); // If the remote MX doesn't support pipelining then wait and check the response. if (!_CanPipeline) { string response = await SmtpStream.ReadAllLinesAsync(); if (!response.StartsWith("250")) { if (response.StartsWith("421")) { return(new MantaOutboundClientSendResult(MantaOutboundClientResult.ServiceNotAvalible, response, _VirtualMta, _MXRecord)); } return(new MantaOutboundClientSendResult(MantaOutboundClientResult.RejectedByRemoteServer, response, _VirtualMta, _MXRecord)); } } return(new MantaOutboundClientSendResult(MantaOutboundClientResult.Success, null, _VirtualMta, _MXRecord)); }
/// <summary> /// Say EHLO/HELO to the server. /// Will also check to see if 8BITMIME is supported. /// </summary> /// <param name="failedCallback">Action to call if hello fail.</param> public async Task <bool> ExecHeloAsync(Action <string> failedCallback) { if (!base.Connected) { return(false); } _LastActive = DateTime.UtcNow; IsActive = true; // We have connected to the MX, Say EHLO. _LastActive = DateTime.UtcNow; await SmtpStream.WriteLineAsync("EHLO " + MtaIpAddress.Hostname); string response = await SmtpStream.ReadAllLinesAsync(); if (response.StartsWith("421")) { failedCallback(response); } _LastActive = DateTime.UtcNow; try { if (!response.StartsWith("2")) { // If server didn't respond with a success code on hello then we should retry with HELO await SmtpStream.WriteLineAsync("HELO " + MtaIpAddress.Hostname); response = await SmtpStream.ReadAllLinesAsync(); _LastActive = DateTime.UtcNow; if (!response.StartsWith("250")) { failedCallback(response); base.Close(); } } else { // Server responded to EHLO // Check to see if it supports 8BITMIME if (response.IndexOf("8BITMIME", StringComparison.OrdinalIgnoreCase) > -1) { _DataTransportMime = SmtpTransportMIME._8BitUTF; } // Check to see if the server supports pipelining if (response.IndexOf("PIPELINING", StringComparison.OrdinalIgnoreCase) > -1) { _CanPipeline = true; } } } catch (IOException) { // Remote Endpoint Disconnected Mid HELO. Most likly Yahoo throttling. } _HasHelloed = true; _LastActive = DateTime.UtcNow; IsActive = false; return(true); }
/// <summary> /// Send the data to the server /// </summary> /// <param name="data">Data to send to the server</param> /// <param name="failedCallback">Action to call if fails to send.</param> public async Task <bool> ExecDataAsync(string data, Action <string> failedCallback, Func <string, Task> successCallbackAsync) { if (!base.Connected) { return(false); } _LastActive = DateTime.UtcNow; IsActive = true; await SmtpStream.WriteLineAsync("DATA"); string response = await SmtpStream.ReadAllLinesAsync(); // If the remote MX supports pipelining then we need to check the MAIL FROM and RCPT to responses. if (_CanPipeline) { // Check MAIL FROM OK. if (!response.StartsWith("250")) { failedCallback(response); IsActive = false; return(false); } // Check RCPT TO OK. response = await SmtpStream.ReadAllLinesAsync(); if (!response.StartsWith("250")) { failedCallback(response); IsActive = false; return(false); } // Get the Data Command response. response = await SmtpStream.ReadAllLinesAsync(); } _LastActive = DateTime.UtcNow; if (!response.StartsWith("354")) { failedCallback(response); IsActive = false; return(false); } // Increment the data commands as server has responded positiely. _DataCommands++; // Send the message data using the correct transport MIME SmtpStream.SetSmtpTransportMIME(_DataTransportMime); await SmtpStream.WriteAsync(data, false); await SmtpStream.WriteAsync(MtaParameters.NewLine + "." + MtaParameters.NewLine, false); _LastActive = DateTime.UtcNow; // Data done so return to 7-Bit mode. SmtpStream.SetSmtpTransportMIME(SmtpTransportMIME._7BitASCII); response = await SmtpStream.ReadAllLinesAsync(); _LastActive = DateTime.UtcNow; IsActive = false; if (!response.StartsWith("250")) { failedCallback(response); } else { await successCallbackAsync(response); } // If max messages have been sent quit the connection. if (_DataCommands >= OutboundRuleManager.GetMaxMessagesPerConnection(MXRecord, MtaIpAddress)) { ExecQuitAsync().Wait(); } return(true); }