public override async Task ExecuteAsync(SmtpSession smtpSession, CancellationToken token) { if (String.IsNullOrEmpty(smtpSession.PendingMail?.FromPath?.Mailbox) || smtpSession.PendingMail?.Recipents?.Count == 0 || smtpSession.PendingMail?.IsBinary == true) { await smtpSession.SendReplyAsync(ReplyCode.BadSequence, "Bad sequence", token); return; } await smtpSession.SendReplyAsync(ReplyCode.StartMail, "Send data, end with .<CR><LF>", token); using (var mailStream = await smtpSession.MailStore.NewMailAsync(smtpSession.PendingMail.FromPath.Mailbox, smtpSession.PendingMail.Recipents, token)) using (var mailWriter = new StreamWriter(mailStream.BodyStream, Encoding.UTF8)) { await mailWriter.WriteLineAsync( $"Received: FROM {smtpSession.ConnectedHost} ({smtpSession.ConnectedIpAddress}) BY {smtpSession.Settings.DomainName} ({smtpSession.IpAddress}); {DateTime.UtcNow:ddd, dd MMM yyy HH:mm:ss zzzz}"); string line; while ((line = await smtpSession.Connection.ReadLineAsync(Encoding.UTF8, token)) != ".") { await mailWriter.WriteLineAsync(line); } } smtpSession.PendingMail = null; await smtpSession.SendReplyAsync(ReplyCode.Okay, "OK", token); }
public void Setup() { SmtpSessionContext context = new SmtpSessionContext(); Mock <ITransport> transportMock = new Mock <ITransport>(MockBehavior.Loose); _handshakeProviderMock = CreateProvider(context, new Result { StatusCode = SmtpStatusCode.OK }); _senderValidationProviderMock = CreateProvider(context, new Result { StatusCode = SmtpStatusCode.OK }); _recipientValidationProviderMock = CreateProvider(context, new Result { StatusCode = SmtpStatusCode.OK }); _messageHandlerMock = CreateProvider(context, new Result { StatusCode = SmtpStatusCode.OK }); _authProviderMock = CreateProvider(context, new Result { StatusCode = SmtpStatusCode.OK }); _session = new SmtpSession(transportMock.Object) { HandshakeProvider = _handshakeProviderMock.Object, SenderValidationProvider = _senderValidationProviderMock.Object, RecipientValidationProvider = _recipientValidationProviderMock.Object, MessageReaderProvider = _messageHandlerMock.Object, AuthProvider = _authProviderMock.Object }; _session.StartSession().Wait(); }
protected bool TryProcessParameterValue( SmtpSession session, string parameterString, out Task errorReport, CancellationToken cancellationToken) { foreach (var parameter in parameterString.Split(new [] { ' ' }, StringSplitOptions.RemoveEmptyEntries)) { int sepIndex = parameter.IndexOf("=", StringComparison.Ordinal); if (sepIndex == -1) { errorReport = session.SendReplyAsync(ReplyCode.InvalidArguments, "Bad parameters", cancellationToken); return(false); } string paramKey = parameter.Substring(0, sepIndex); string paramValue = parameter.Substring(sepIndex + 1); if (!TryProcessParameter(session, paramKey, paramValue)) { errorReport = session.SendReplyAsync( ReplyCode.ParameterNotImplemented, "Parameter not implemented", cancellationToken); return(false); } } errorReport = null; return(true); }
private static string OnMessageArrived(SmtpSession session) { var mime = MimeKit.MimeMessage.Load(session.ContentStream); Console.WriteLine(mime.TextBody); return("OK"); }
public Task <SmtpSession> StoreSessionAsync(SmtpSession session) { if (session.SessionId == 0) { return(this.InsertSessionAsync(session)); } return(this.UpdateSessionAsync(session)); }
public BinaryDataCommand( SecurableConnection connection, SmtpSession session, IMailQueue mailQueue, IMailBuilder builder) { _connection = connection; _session = session; _mailQueue = mailQueue; _builder = builder; }
/// <summary> /// The send button_ click. /// </summary> /// <param name="sender"> /// The sender. /// </param> /// <param name="e"> /// The e. /// </param> private void sendButton_Click(object sender, RoutedEventArgs e) { if (string.IsNullOrEmpty(this.server.Text) || string.IsNullOrEmpty([email protected]) || string.IsNullOrEmpty(this.to.Text)) { MessageBox.Show( "All the text boxes are required, fill them in please.", "Papercut", MessageBoxButton.OK, MessageBoxImage.Warning); return; } if (!emailRegex.IsMatch([email protected]) || !emailRegex.IsMatch(this.to.Text)) { MessageBox.Show( "You need to enter valid email addresses.", "Papercut", MessageBoxButton.OK, MessageBoxImage.Warning); return; } var session = new SmtpSession { Sender = this.server.Text.Trim(), MailFrom = [email protected] }; session.Recipients.Add(this.to.Text); session.Message = File.ReadAllBytes(this.messageFilename); this.worker = Task.Factory.StartNew( () => { using (var client = new SmtpClient(session)) { client.Send(); } }); this.worker.ContinueWith( (t) => { // Save settings for the next time Settings.Default.ForwardServer = this.server.Text; Settings.Default.ForwardTo = this.to.Text; Settings.Default.ForwardFrom = [email protected]; Settings.Default.Save(); this.working = false; this.sendingLabel.Visibility = Visibility.Hidden; this.DialogResult = true; }, TaskScheduler.FromCurrentSynchronizationContext()); this.working = true; this.sendButton.IsEnabled = false; this.sendingLabel.Visibility = Visibility.Visible; }
public override Task ExecuteAsync(SmtpSession smtpSession, CancellationToken token) { if (smtpSession.PendingMail == null) { return(smtpSession.SendReplyAsync(ReplyCode.BadSequence, "RCPT not valid now", token)); } Match toMatch = FromExpression.Match(Arguments); if (!toMatch.Success) { return(smtpSession.SendReplyAsync(ReplyCode.InvalidArguments, "Bad FROM address", token)); } string sourceRoute = toMatch.Groups[1].Value; string mailBox = toMatch.Groups[2].Value; if (!String.IsNullOrEmpty(sourceRoute)) { return(smtpSession.SendReplyAsync(ReplyCode.NameNotAllowed, "Forwarding not supported", token)); } string parameterString = toMatch.Groups[3].Value; Task errorReport; if (!TryProcessParameterValue(smtpSession, parameterString, out errorReport, token)) { return(errorReport); } string[] mailboxParts = mailBox.Split('@'); if (mailboxParts.Length != 2) { return(smtpSession.SendReplyAsync(ReplyCode.InvalidArguments, "Invalid mailbox name", token)); } string domain = mailboxParts[1]; if (!smtpSession.IsAuthenticated && smtpSession.Settings.RelayDomains?.Contains(domain, StringComparer.OrdinalIgnoreCase) != true) { return(smtpSession.SendReplyAsync(ReplyCode.MailboxUnavailable, "Invalid mailbox", token)); } smtpSession.PendingMail.Recipents.Add(mailBox); return(smtpSession.SendReplyAsync(ReplyCode.Okay, token)); }
public Task <SmtpSession> StoreSessionAsync(SmtpSession session) { var sessionId = 1; if (this._sessions.Count > 0) { sessionId = this._sessions.Max(x => x.SessionId) + 1; } session.SessionId = sessionId; this._sessions.Add(session); return(Task.FromResult(session)); }
public async Task <SmtpSession[]> GetSessionsAsync(DateTime?oldestDate = null, DateTime?newestDate = null, string username = null) { var result = new List <SmtpSession>(); var query = "SELECT * FROM \"Sessions\""; if (oldestDate.HasValue || newestDate.HasValue || !string.IsNullOrWhiteSpace(username)) { query += " WHERE "; var predicates = new List <string>(); if (oldestDate.HasValue) { predicates.Add("\"SessionStartTime\" >= @oldestTime"); } if (newestDate.HasValue) { predicates.Add("\"SessionStartTime\" <= @newestTime"); } if (username != null) { predicates.Add("\"Username\" LIKE @username"); } } using (var connection = this.GetConnection()) { var dataSessions = await connection.QueryAsync <DataSession>(query, new { oldestTime = oldestDate, newestTime = newestDate, username = username }); foreach (var dataSession in dataSessions) { var session = new SmtpSession { RemoteIp = dataSession.RemoteIP, SessionEndTime = dataSession.SessionEndTime, SessionId = dataSession.Id, SessionStartTime = dataSession.SessionStartTime, Username = dataSession.Username }; result.Add(session); } } return(result.ToArray()); }
public TestConnection(ITestOutputHelper output) { (Stream a, Stream b) = PairedStream.Create(); LocalStream = new RedirectableStream(a); Reader = new StreamReader(LocalStream); Writer = new StreamWriter(LocalStream) { AutoFlush = true }; var builder = new ContainerBuilder(); builder.RegisterAssemblyTypes(typeof(SmtpSession).GetTypeInfo().Assembly) .Where(t => t.GetTypeInfo().GetCustomAttribute <SmtpCommandAttribute>() != null) .Keyed <ISmtpCommand>(t => t.GetTypeInfo().GetCustomAttribute <SmtpCommandAttribute>().Name); builder.RegisterInstance(TestHelpers.MakeSettings("test.vaettir.net")) .As <AgentSettings>() .As <AgentSettings>(); builder.RegisterType <SmtpSession>() .As <SmtpSession>() .As <ISmtpMessageChannel>() .As <IMailBuilder>() .As <IProtocolSession>(); builder.RegisterType <SmtpAuthenticationTransport>() .As <IAuthenticationTransport>(); builder.RegisterInstance(new SecurableConnection(b, PrivateKeyHolder.Fixed(s_serverCert))) .As <IConnectionSecurity>() .As <SecurableConnection>(); builder.RegisterInstance(new TestOutputLogger(output)) .As <ILogger>(); builder.RegisterInstance(new ConnectionInformation("127.0.0.1", "128.0.0.1")); Container = builder.Build(); Connection = Container.Resolve <SecurableConnection>(); Session = Container.Resolve <SmtpSession>(); CancellationTokenSource = new CancellationTokenSource(); CancellationToken token = CancellationTokenSource.Token; SessionTask = Task.Run(() => Session.RunAsync(token), token); }
protected bool CheckRule(MimeKit.MimeMessage message, SmtpSession session) { if (message == null || session == null) { return(false); } foreach (var address in message.Bcc) { var mailAddress = address as MimeKit.MailboxAddress; if (mailAddress != null) { } } return(false); }
public override Task ExecuteAsync(SmtpSession smtpSession, CancellationToken token) { if (smtpSession.PendingMail != null) { return(smtpSession.SendReplyAsync(ReplyCode.BadSequence, "MAIL not allowed now", CancellationToken.None)); } Match fromMatch = FromExpression.Match(Arguments); if (!fromMatch.Success) { return(smtpSession.SendReplyAsync(ReplyCode.InvalidArguments, "Bad FROM address", CancellationToken.None)); } string sourceRoute = fromMatch.Groups[1].Value; string mailBox = fromMatch.Groups[2].Value; string parameterText = fromMatch.Groups[3].Value; ImmutableList <string> sourceRouteList = null; if (!String.IsNullOrEmpty(sourceRoute)) { sourceRouteList = ImmutableList.CreateRange(sourceRoute.Split(',')); } Task errorReport; if (!TryProcessParameterValue(smtpSession, parameterText, out errorReport, token)) { return(errorReport); } if (smtpSession.IsAuthenticated && !smtpSession.UserStore.CanUserSendAs(smtpSession.AuthenticatedUser, mailBox)) { return(smtpSession.SendReplyAsync(ReplyCode.MailboxUnavailable, "Invalid mailbox", token)); } smtpSession.PendingMail = new SmtpMailMessage( new SmtpPath( sourceRouteList, mailBox)); return(smtpSession.SendReplyAsync(ReplyCode.Okay, token)); }
public SessionSummary ToSessionSummary(SmtpSession core) { if (core == null) { return(null); } var result = new SessionSummary { Id = core.SessionId, RemoteIp = core.RemoteIp, SessionEndTime = core.SessionEndTime, SessionId = this._dataEncryptor.EncryptSessionId(core.SessionId), SessionStartTime = core.SessionStartTime, Username = core.Username }; return(result); }
protected override bool TryProcessParameter(SmtpSession session, string key, string value) { switch (key.ToUpperInvariant()) { case "BODY": switch (value.ToUpperInvariant()) { case "7BIT": case "8BITMIME": return(true); case "BINARYMIME": session.PendingMail.IsBinary = true; return(true); } return(false); default: return(base.TryProcessParameter(session, key, value)); } }
public SessionDetails GetSessionDetails(SmtpSession session, SmtpSessionChatter[] sessionChatter, Core.MessageSummary[] messageSummaries) { if (session == null) { return(null); } var result = new SessionDetails { Id = session.SessionId, MessageSummaries = this.ToMessageSummaries(messageSummaries), RemoteIp = session.RemoteIp, SessionChatter = this.GetSessionChatter(sessionChatter), SessionEndTime = session.SessionEndTime, SessionId = this._dataEncryptor.EncryptSessionId(session.SessionId), SessionStartTime = session.SessionStartTime, Username = session.Username }; return(result); }
public override async Task ExecuteAsync(SmtpSession smtpSession, CancellationToken token) { ImmutableList <string> encryptedExtensions = ImmutableList.CreateRange( new[] { "AUTH " + String.Join(" ", smtpSession.ImplementationFactory.Authentication.GetSupported()), }); smtpSession.ConnectedHost = Arguments; ImmutableList <string> plainTextExtensions = PlainTextExtensions; var extensions = GeneralExtensions.Concat(smtpSession.Connection.IsEncrypted ? encryptedExtensions : plainTextExtensions); if (smtpSession.Connection.Certificate != null && !smtpSession.Connection.IsEncrypted) { extensions = extensions.Concat(new[] { "STARTTLS" }); } await smtpSession.SendReplyAsync(ReplyCode.Okay, true, $"{smtpSession.Settings.DomainName} greets {Arguments}", token); await smtpSession.SendReplyAsync(ReplyCode.Okay, extensions, token); }
public async Task <SmtpSession> GetSessionByIdAsync(int id) { using (var connection = this.GetConnection()) { var session = await connection.QuerySingleOrDefaultAsync <DataSession>("SELECT * FROM Sessions WHERE Id = @id", new { id = id }); if (session != null) { var result = new SmtpSession { RemoteIp = session.RemoteIP, SessionEndTime = session.SessionEndTime, SessionId = session.Id, SessionStartTime = session.SessionStartTime, Username = session.Username }; return(result); } return(null); } }
public override async Task ExecuteAsync(SmtpSession smtpSession, CancellationToken token) { string[] parts = Arguments.Split(new [] { ' ' }, 2); if (parts == null || parts.Length == 0 || parts.Length > 2) { await smtpSession.SendReplyAsync(ReplyCode.InvalidArguments, "Expected mechanism and optional initial response", token); return; } string mechanismName = parts[0]; IAuthenticationMechanism mechanism = smtpSession.ImplementationFactory.Authentication.Get(mechanismName); if (mechanism == null) { await smtpSession.SendReplyAsync(ReplyCode.InvalidArguments, "Unknown mechanism", token); return; } var authSession = mechanism.CreateSession(smtpSession); UserData userData; try { userData = await authSession.AuthenticateAsync(smtpSession.UserStore, token, false); } catch (ArgumentException) { await smtpSession.SendReplyAsync(ReplyCode.InvalidArguments, "Invalid arguments", token); return; } smtpSession.AuthenticatedUser = userData; await smtpSession.SendReplyAsync(ReplyCode.AuthenticationComplete, "Authentication unsuccessful", token); }
private async Task <SmtpSession> InsertSessionAsync(SmtpSession session) { using (var connection = this.GetConnection()) { var query = @" INSERT INTO ""public"".""Sessions"" (""SessionStartTime"", ""SessionEndTime"", ""RemoteIP"", ""Username"") VALUES (@sessionStartTime, @sessionEndTime, @remoteIP, @username) RETURNING ""Id""; "; var id = await connection.ExecuteScalarAsync <int>(query, new { sessionStartTime = session.SessionStartTime, sessionEndTime = session.SessionEndTime, remoteIp = session.RemoteIp, username = session.Username }); session.SessionId = id; return(session); } }
private async Task <SmtpSession> UpdateSessionAsync(SmtpSession session) { using (var connection = this.GetConnection()) { var query = @" UPDATE Sessions SET SessionStartTime = @sessionStartTime, SessionEndTime = @sessionEndTime, RemoteIP = @remoteIP, Username = @username WHERE Id = @id"; await connection.ExecuteAsync(query, new { sessionStartTime = session.SessionStartTime, sessionEndTime = session.SessionEndTime, remoteIp = session.RemoteIp, username = session.Username }); return(session); } }
//public int ExtractData(NetworkTcpSession tcpSession, NetworkHost sourceHost, NetworkHost destinationHost, IEnumerable<PacketParser.Packets.AbstractPacket> packetList) { public int ExtractData(NetworkTcpSession tcpSession, bool transferIsClientToServer, IEnumerable <PacketParser.Packets.AbstractPacket> packetList) { /* * NetworkHost sourceHost, destinationHost; * if (transferIsClientToServer) { * sourceHost = tcpSession.Flow.FiveTuple.ClientHost; * destinationHost = tcpSession.Flow.FiveTuple.ServerHost; * } * else { * sourceHost = tcpSession.Flow.FiveTuple.ServerHost; * destinationHost = tcpSession.Flow.FiveTuple.ClientHost; * }*/ SmtpSession smtpSession; if (this.smtpSessionList.ContainsKey(tcpSession)) { smtpSession = this.smtpSessionList[tcpSession]; } else { smtpSession = new SmtpSession(); this.smtpSessionList.Add(tcpSession, smtpSession); } Packets.TcpPacket tcpPacket = null; Packets.SmtpPacket smtpPacket = null; foreach (Packets.AbstractPacket p in packetList) { if (p.GetType() == typeof(Packets.TcpPacket)) { tcpPacket = (Packets.TcpPacket)p; } else if (p.GetType() == typeof(Packets.SmtpPacket)) { smtpPacket = (Packets.SmtpPacket)p; } } if (smtpPacket != null) { if (smtpPacket.ClientToServer) { if (smtpSession.State == SmtpSession.SmtpState.Username) { string base64Username = smtpPacket.ReadLine().Trim(); try { byte[] usernameBytes = System.Convert.FromBase64String(base64Username); smtpSession.Username = System.Text.ASCIIEncoding.ASCII.GetString(usernameBytes); } catch (FormatException e) { } } else if (smtpSession.State == SmtpSession.SmtpState.Password) { string base64Password = smtpPacket.ReadLine().Trim(); try { byte[] passwordBytes = System.Convert.FromBase64String(base64Password); smtpSession.Password = System.Text.ASCIIEncoding.ASCII.GetString(passwordBytes); } catch (FormatException e) { } } else if (smtpSession.State == SmtpSession.SmtpState.Data) { //write data to file until we receive "\n.\n" could also be \r\n.\r\n smtpSession.AddData(smtpPacket.ParentFrame.Data, smtpPacket.PacketStartIndex, smtpPacket.PacketLength); //check if state has transitioned over to footer if (smtpSession.State == SmtpSession.SmtpState.Footer) { Mime.Email email = new Mime.Email(smtpSession.DataStream, base.MainPacketHandler, tcpPacket, transferIsClientToServer, tcpSession, ApplicationLayerProtocol.Smtp, FileTransfer.FileStreamAssembler.FileAssmeblyRootLocation.destination); } } else { foreach (KeyValuePair <string, string> requestCommandAndArgument in smtpPacket.RequestCommandsAndArguments) { if (requestCommandAndArgument.Key.Equals(SmtpPacket.ClientCommands.HELO.ToString(), StringComparison.InvariantCultureIgnoreCase)) { string clientDomain = requestCommandAndArgument.Value; } else if (requestCommandAndArgument.Key.Equals(SmtpPacket.ClientCommands.EHLO.ToString(), StringComparison.InvariantCultureIgnoreCase)) { string clientDomain = requestCommandAndArgument.Value; } else if (requestCommandAndArgument.Key.Equals(SmtpPacket.ClientCommands.AUTH.ToString(), StringComparison.InvariantCultureIgnoreCase)) { if (requestCommandAndArgument.Value.Trim().StartsWith("LOGIN", StringComparison.InvariantCultureIgnoreCase)) { //if (requestCommandAndArgument.Value.ToUpper().Contains("LOGIN")) { smtpSession.State = SmtpSession.SmtpState.AuthLogin; //SMTP clients sometimes send the email address right away like this: "AUTH LOGIN aGVqaG9wcEBpbnRlcm5ldC5zZQ==" if (requestCommandAndArgument.Value.Length > "LOGIN ".Length) { try { string base64Username = requestCommandAndArgument.Value.Substring("LOGIN ".Length).Trim(); byte[] usernameBytes = System.Convert.FromBase64String(base64Username); smtpSession.Username = System.Text.ASCIIEncoding.ASCII.GetString(usernameBytes); } catch (ArgumentException) { } } } else if (requestCommandAndArgument.Value.Trim().StartsWith("PLAIN", StringComparison.InvariantCultureIgnoreCase)) { //AUTH PLAIN <base64-encoded username and password> smtpSession.State = SmtpSession.SmtpState.AuthLogin; //SMTP clients sometimes send the email address right away like this: "AUTH LOGIN aGVqaG9wcEBpbnRlcm5ldC5zZQ==" if (requestCommandAndArgument.Value.Length > "PLAIN ".Length) { try { string base64 = requestCommandAndArgument.Value.Substring("PLAIN ".Length).Trim(); NetworkCredential cred = SmtpPacketHandler.ExtractBase64EncodedAuthPlainCredential(base64, smtpPacket.ParentFrame, tcpSession, ApplicationLayerProtocol.Smtp); if (cred != null) { //this.MainPacketHandler.OnCredentialDetected(new Events.CredentialEventArgs(cred)); this.MainPacketHandler.AddCredential(cred); } } catch (ArgumentException) { } } } } else if (requestCommandAndArgument.Key.Equals(SmtpPacket.ClientCommands.MAIL.ToString(), StringComparison.InvariantCultureIgnoreCase)) { if (requestCommandAndArgument.Value.StartsWith("FROM", StringComparison.InvariantCultureIgnoreCase)) { int colonIndex = requestCommandAndArgument.Value.IndexOf(':'); if (colonIndex > 0 && requestCommandAndArgument.Value.Length > colonIndex + 1) { smtpSession.MailFrom = requestCommandAndArgument.Value.Substring(colonIndex + 1).Trim(); } } } else if (requestCommandAndArgument.Key.Equals(SmtpPacket.ClientCommands.RCPT.ToString(), StringComparison.InvariantCultureIgnoreCase)) { if (requestCommandAndArgument.Value.StartsWith("TO", StringComparison.InvariantCultureIgnoreCase)) { int colonIndex = requestCommandAndArgument.Value.IndexOf(':'); if (colonIndex > 0 && requestCommandAndArgument.Value.Length > colonIndex + 1) { smtpSession.AddRecipient(requestCommandAndArgument.Value.Substring(colonIndex + 1).Trim()); } } } else if (requestCommandAndArgument.Key.Equals(SmtpPacket.ClientCommands.DATA.ToString(), StringComparison.InvariantCultureIgnoreCase)) { smtpSession.State = SmtpSession.SmtpState.Data; } else if (requestCommandAndArgument.Key.Equals(SmtpPacket.ClientCommands.STARTTLS.ToString(), StringComparison.InvariantCultureIgnoreCase)) { smtpSession.State = SmtpSession.SmtpState.StartTlsRequested; } } } } else //server to client { foreach (KeyValuePair <int, string> replyCodeAndArgument in smtpPacket.Replies) { if (replyCodeAndArgument.Key == 334) //AUTH LOGIN { if (replyCodeAndArgument.Value.Equals("VXNlcm5hbWU6")) { smtpSession.State = SmtpSession.SmtpState.Username; } else if (replyCodeAndArgument.Value.Equals("UGFzc3dvcmQ6")) { smtpSession.State = SmtpSession.SmtpState.Password; } } else if (replyCodeAndArgument.Key == 235) //AUTHENTICATION SUCCESSFUL { base.MainPacketHandler.AddCredential(new NetworkCredential(tcpSession.ClientHost, tcpSession.ServerHost, smtpPacket.PacketTypeDescription, smtpSession.Username, smtpSession.Password, smtpPacket.ParentFrame.Timestamp)); smtpSession.State = SmtpSession.SmtpState.Authenticated; } else if (replyCodeAndArgument.Key >= 500) //error { smtpSession.State = SmtpSession.SmtpState.None; } else if (replyCodeAndArgument.Key == 354) //DATA "Start mail input; end with <CRLF>.<CRLF>" { smtpSession.State = SmtpSession.SmtpState.Data; } else if (replyCodeAndArgument.Key == 250) //"Requested mail action okay, completed" { if (smtpSession.State == SmtpSession.SmtpState.Footer) { //smtpSession.DataStream.Seek(0, System.IO.SeekOrigin.Begin); smtpSession.DataStream = new System.IO.MemoryStream(); //System.Diagnostics.Debugger.Break(); } smtpSession.State = SmtpSession.SmtpState.None;//Added in order to reset state when multiple SMTP sessions are sent within the same TCP session } else if (replyCodeAndArgument.Key == 220) { if (smtpSession.State == SmtpSession.SmtpState.StartTlsRequested) { tcpSession.ProtocolFinder.SetConfirmedApplicationLayerProtocol(ApplicationLayerProtocol.Ssl, false); } } } } //There was a SMTP packet, so treat this as a sucsessfull extraction return(tcpPacket.PayloadDataLength); } else //smtpPacket == null { return(0); } }
public int ExtractData(NetworkTcpSession tcpSession, NetworkHost sourceHost, NetworkHost destinationHost, IEnumerable <PacketParser.Packets.AbstractPacket> packetList) { SmtpSession smtpSession; if (this.smtpSessionList.ContainsKey(tcpSession)) { smtpSession = this.smtpSessionList[tcpSession]; } else { smtpSession = new SmtpSession(); this.smtpSessionList.Add(tcpSession, smtpSession); } Packets.TcpPacket tcpPacket = null; Packets.SmtpPacket smtpPacket = null; foreach (Packets.AbstractPacket p in packetList) { if (p.GetType() == typeof(Packets.TcpPacket)) { tcpPacket = (Packets.TcpPacket)p; } else if (p.GetType() == typeof(Packets.SmtpPacket)) { smtpPacket = (Packets.SmtpPacket)p; } } if (smtpPacket != null) { if (smtpPacket.ClientToServer) { if (smtpSession.State == SmtpSession.SmtpState.Username) { string base64Username = smtpPacket.ReadLine().Trim(); try { byte[] usernameBytes = System.Convert.FromBase64String(base64Username); smtpSession.Username = System.Text.ASCIIEncoding.ASCII.GetString(usernameBytes); } catch (FormatException e) { } } else if (smtpSession.State == SmtpSession.SmtpState.Password) { string base64Password = smtpPacket.ReadLine().Trim(); try { byte[] passwordBytes = System.Convert.FromBase64String(base64Password); smtpSession.Password = System.Text.ASCIIEncoding.ASCII.GetString(passwordBytes); } catch (FormatException e) { } } else if (smtpSession.State == SmtpSession.SmtpState.Data) { //write data to file until we receive "\n.\n" could also be \r\n.\r\n smtpSession.AddData(smtpPacket.ParentFrame.Data, smtpPacket.PacketStartIndex, smtpPacket.PacketLength); //check if state has transitioned over to footer if (smtpSession.State == SmtpSession.SmtpState.Footer) { Mime.UnbufferedReader ur = new PacketParser.Mime.UnbufferedReader(smtpSession.DataStream); string from = null; string to = null; string subject = null; string messageId = null; System.Collections.Specialized.NameValueCollection rootAttributes = null; foreach (Mime.MultipartPart multipart in Mime.PartBuilder.GetParts(ur)) { if (rootAttributes == null) { from = multipart.Attributes["From"]; to = multipart.Attributes["To"]; subject = multipart.Attributes["Subject"]; messageId = multipart.Attributes["Message-ID"]; rootAttributes = multipart.Attributes; } base.MainPacketHandler.OnParametersDetected(new PacketParser.Events.ParametersEventArgs(smtpPacket.ParentFrame.FrameNumber, sourceHost, destinationHost, "TCP " + tcpPacket.SourcePort, "TCP " + tcpPacket.DestinationPort, multipart.Attributes, tcpPacket.ParentFrame.Timestamp, "SMTP packet")); string contentType = multipart.Attributes["Content-Type"]; string charset = multipart.Attributes["charset"]; Encoding encoding = null; if (charset != null && charset.Length > 0) { try { encoding = System.Text.Encoding.GetEncoding(charset); } catch { }; } bool attachment = false; string contentDisposition = multipart.Attributes["Content-Disposition"]; if (contentDisposition != null && contentDisposition.Contains("attachment")) { attachment = true; } if (!attachment && contentType == null || contentType.Equals("text/plain", StringComparison.InvariantCultureIgnoreCase)) { //print the data as text //string textData = null; byte[] textDataBytes = null; if (multipart.Attributes["Content-Transfer-Encoding"] == "quoted-printable") { textDataBytes = Utils.ByteConverter.ReadQuotedPrintable(multipart.Data).ToArray(); //textData = Utils.ByteConverter.ReadString(); } else if (multipart.Attributes["Content-Transfer-Encoding"] == "base64") { textDataBytes = System.Convert.FromBase64String(Utils.ByteConverter.ReadString(multipart.Data)); //textData = Utils.ByteConverter.ReadString(); } else { textDataBytes = multipart.Data; //textData = Utils.ByteConverter.ReadString(); } string textData = null; if (encoding == null) { textData = Utils.ByteConverter.ReadString(textDataBytes); } else { textData = encoding.GetString(textDataBytes); } if (textData != null) { //System.Collections.Specialized.NameValueCollection tmpCol=new System.Collections.Specialized.NameValueCollection(); //tmpCol.Add("e-mail", textData); //base.MainPacketHandler.OnParametersDetected(new PacketParser.Events.ParametersEventArgs(smtpPacket.ParentFrame.FrameNumber, sourceHost, destinationHost, "TCP "+tcpPacket.SourcePort, "TCP "+tcpPacket.DestinationPort, tmpCol, tcpPacket.ParentFrame.Timestamp, "SMTP packet")); System.Collections.Specialized.NameValueCollection aggregatedAttributes = new System.Collections.Specialized.NameValueCollection(); aggregatedAttributes.Add(rootAttributes); aggregatedAttributes.Add(multipart.Attributes); base.MainPacketHandler.OnMessageDetected(new PacketParser.Events.MessageEventArgs(ApplicationLayerProtocol.Smtp, sourceHost, destinationHost, smtpPacket.ParentFrame.FrameNumber, smtpPacket.ParentFrame.Timestamp, from, to, subject, textData, aggregatedAttributes)); } } else { //store the stuff to disk string filename = multipart.Attributes["name"]; if (filename == null || filename.Length == 0) { filename = multipart.Attributes["filename"]; } if (filename == null || filename.Length == 0) { if (subject != null && subject.Length > 3) { filename = Utils.StringManglerUtil.ConvertToFilename(subject, 10); } else if (messageId != null && messageId.Length > 3) { filename = Utils.StringManglerUtil.ConvertToFilename(messageId, 10); } if (filename == null || filename.Length < 3) { filename = "email_" + (multipart.GetHashCode() % 1000); } string extension = Utils.StringManglerUtil.GetExtension(contentType); if (extension == null || extension.Length < 1) { extension = "dat"; } filename = filename + "." + extension; } //check if filename is encoded as '?CharacterSet?Enum(Q,B)?', for example '=?UTF-8?B?IE1ldGhvZA==?=' RFC2047 /* * if (Mime.Rfc2047Parser.IsRfc2047String(filename)) { * try { * filename = Mime.Rfc2047Parser.ParseRfc2047String(filename); * } * catch (Exception) { } * }*/ List <byte> fileData = new List <byte>(); if (multipart.Attributes["Content-Transfer-Encoding"] == "base64") { //decode base64 stuff int index = 0; while (index < multipart.Data.Length) { string base64 = Utils.ByteConverter.ReadLine(multipart.Data, ref index); if (base64 == null && index < multipart.Data.Length) { //read the remaining data base64 = Utils.ByteConverter.ReadString(multipart.Data, index, multipart.Data.Length - index, false, false); index = multipart.Data.Length; } #if DEBUG if (base64 == null) { System.Diagnostics.Debugger.Break(); } #endif //if (base64 != null && base64.Length > 0) { try { fileData.AddRange(Convert.FromBase64String(base64)); } catch (FormatException e) { } } } else if (multipart.Attributes["Content-Transfer-Encoding"] == "quoted-printable") { //must be decoded according to http://www.ietf.org/rfc/rfc2045.txt fileData = Utils.ByteConverter.ReadQuotedPrintable(multipart.Data); } else { //Add the raw data fileData.AddRange(multipart.Data); } if (fileData != null && fileData.Count > 0) { FileTransfer.FileStreamAssembler assembler = new FileTransfer.FileStreamAssembler(MainPacketHandler.FileStreamAssemblerList, sourceHost, tcpPacket.SourcePort, destinationHost, tcpPacket.DestinationPort, true, FileTransfer.FileStreamTypes.SMTP, filename, "/", fileData.Count, fileData.Count, "E-mail From: " + from + " To: " + to + " Subject: " + subject, filename, tcpPacket.ParentFrame.FrameNumber, tcpPacket.ParentFrame.Timestamp); if (assembler.TryActivate()) { assembler.AddData(fileData.ToArray(), tcpPacket.SequenceNumber); //assembler.FinishAssembling(); } else { assembler.Clear(); assembler.FinishAssembling(); } } } } } } else { foreach (KeyValuePair <string, string> requestCommandAndArgument in smtpPacket.RequestCommandsAndArguments) { if (requestCommandAndArgument.Key.Equals(SmtpPacket.ClientCommands.HELO.ToString(), StringComparison.InvariantCultureIgnoreCase)) { string clientDomain = requestCommandAndArgument.Value; } else if (requestCommandAndArgument.Key.Equals(SmtpPacket.ClientCommands.EHLO.ToString(), StringComparison.InvariantCultureIgnoreCase)) { string clientDomain = requestCommandAndArgument.Value; } else if (requestCommandAndArgument.Key.Equals(SmtpPacket.ClientCommands.AUTH.ToString(), StringComparison.InvariantCultureIgnoreCase)) { if (requestCommandAndArgument.Value.ToUpper().Contains("LOGIN")) { smtpSession.State = SmtpSession.SmtpState.AuthLogin; } } else if (requestCommandAndArgument.Key.Equals(SmtpPacket.ClientCommands.MAIL.ToString(), StringComparison.InvariantCultureIgnoreCase)) { if (requestCommandAndArgument.Value.StartsWith("FROM", StringComparison.InvariantCultureIgnoreCase)) { int colonIndex = requestCommandAndArgument.Value.IndexOf(':'); if (colonIndex > 0 && requestCommandAndArgument.Value.Length > colonIndex + 1) { smtpSession.MailFrom = requestCommandAndArgument.Value.Substring(colonIndex + 1).Trim(); } } } else if (requestCommandAndArgument.Key.Equals(SmtpPacket.ClientCommands.RCPT.ToString(), StringComparison.InvariantCultureIgnoreCase)) { if (requestCommandAndArgument.Value.StartsWith("TO", StringComparison.InvariantCultureIgnoreCase)) { int colonIndex = requestCommandAndArgument.Value.IndexOf(':'); if (colonIndex > 0 && requestCommandAndArgument.Value.Length > colonIndex + 1) { smtpSession.AddRecipient(requestCommandAndArgument.Value.Substring(colonIndex + 1).Trim()); } } } else if (requestCommandAndArgument.Key.Equals(SmtpPacket.ClientCommands.DATA.ToString(), StringComparison.InvariantCultureIgnoreCase)) { smtpSession.State = SmtpSession.SmtpState.Data; } #if DEBUG base.MainPacketHandler.OnParametersDetected(new Events.ParametersEventArgs(tcpPacket.ParentFrame.FrameNumber, sourceHost, destinationHost, "TCP " + tcpPacket.SourcePort, "TCP " + tcpPacket.DestinationPort, smtpPacket.RequestCommandsAndArguments, tcpPacket.ParentFrame.Timestamp, "SMTP Request")); #endif } } /*} * else if(smtpPacket.RequestCommand != null) { * if(smtpPacket.RequestCommand.Equals(SmtpPacket.ClientCommands.HELO.ToString(), StringComparison.InvariantCultureIgnoreCase)) { * string clientDomain = smtpPacket.RequestArgument; * } * else if(smtpPacket.RequestCommand.Equals(SmtpPacket.ClientCommands.EHLO.ToString(), StringComparison.InvariantCultureIgnoreCase)) { * string clientDomain = smtpPacket.RequestArgument; * } * else if(smtpPacket.RequestCommand.Equals(SmtpPacket.ClientCommands.AUTH.ToString(), StringComparison.InvariantCultureIgnoreCase)) { * if(smtpPacket.RequestArgument.ToUpper().Contains("LOGIN")) * smtpSession.State = SmtpSession.SmtpState.AuthLogin; * } * else if(smtpPacket.RequestCommand.Equals(SmtpPacket.ClientCommands.MAIL.ToString(), StringComparison.InvariantCultureIgnoreCase)) { * if(smtpPacket.RequestArgument.StartsWith("FROM", StringComparison.InvariantCultureIgnoreCase)) { * int colonIndex = smtpPacket.RequestArgument.IndexOf(':'); * if(colonIndex>0 && smtpPacket.RequestArgument.Length > colonIndex+1) * smtpSession.MailFrom = smtpPacket.RequestArgument.Substring(colonIndex+1).Trim(); * } * } * else if(smtpPacket.RequestCommand.Equals(SmtpPacket.ClientCommands.RCPT.ToString(), StringComparison.InvariantCultureIgnoreCase)) { * if(smtpPacket.RequestArgument.StartsWith("TO", StringComparison.InvariantCultureIgnoreCase)) { * int colonIndex = smtpPacket.RequestArgument.IndexOf(':'); * if(colonIndex>0 && smtpPacket.RequestArgument.Length > colonIndex+1) * smtpSession.AddRecipient(smtpPacket.RequestArgument.Substring(colonIndex+1).Trim()); * } * } * else if(smtpPacket.RequestCommand.Equals(SmtpPacket.ClientCommands.DATA.ToString(), StringComparison.InvariantCultureIgnoreCase)) { * smtpSession.State = SmtpSession.SmtpState.Data; * } * }*/ } else //server to client { foreach (KeyValuePair <int, string> replyCodeAndArgument in smtpPacket.Replies) { if (replyCodeAndArgument.Key == 334) //AUTH LOGIN { if (replyCodeAndArgument.Value.Equals("VXNlcm5hbWU6")) { smtpSession.State = SmtpSession.SmtpState.Username; } else if (replyCodeAndArgument.Value.Equals("UGFzc3dvcmQ6")) { smtpSession.State = SmtpSession.SmtpState.Password; } } else if (replyCodeAndArgument.Key == 235) //AUTHENTICATION SUCCESSFUL { base.MainPacketHandler.AddCredential(new NetworkCredential(tcpSession.ClientHost, tcpSession.ServerHost, smtpPacket.PacketTypeDescription, smtpSession.Username, smtpSession.Password, smtpPacket.ParentFrame.Timestamp)); smtpSession.State = SmtpSession.SmtpState.Authenticated; } else if (replyCodeAndArgument.Key >= 500) //error { smtpSession.State = SmtpSession.SmtpState.None; } else if (replyCodeAndArgument.Key == 354) //DATA "Start mail input; end with <CRLF>.<CRLF>" { smtpSession.State = SmtpSession.SmtpState.Data; } else if (replyCodeAndArgument.Key == 250) //"Requested mail action okay, completed" { smtpSession.State = SmtpSession.SmtpState.None; } } } //There was a SMTP packet, so treat this as a sucsessfull extraction return(tcpPacket.PayloadDataLength); } else //smtpPacket == null { return(0); } }
public override async Task ExecuteAsync(SmtpSession smtpSession, CancellationToken token) { if (String.IsNullOrEmpty(smtpSession.PendingMail?.FromPath?.Mailbox) || smtpSession.PendingMail?.Recipents?.Count == 0 || smtpSession.PendingMail?.IsBinary != true) { await smtpSession.SendReplyAsync(ReplyCode.BadSequence, "Bad sequence", token); return; } string[] parts = Arguments?.Split(' '); if (parts == null || parts.Length == 0 || parts.Length > 2) { await smtpSession.SendReplyAsync(ReplyCode.InvalidArguments, "Length required, optional LAST", token); return; } int length; if (!Int32.TryParse(parts[0], out length) || length < 1) { await smtpSession.SendReplyAsync(ReplyCode.InvalidArguments, "Length must be positive integer", token); return; } bool last = false; if (parts.Length == 2) { if (!String.Equals("LAST", parts[1])) { await smtpSession.SendReplyAsync(ReplyCode.InvalidArguments, "LAST expected", token); return; } last = true; } using (var mailReference = await smtpSession.MailStore.NewMailAsync(smtpSession.PendingMail.FromPath.Mailbox, smtpSession.PendingMail.Recipents, token)) { using (var mailStream = mailReference.BodyStream) { byte[] chunk = new byte[1000]; int totalRead = 0; do { int toRead = Math.Min((int)chunk.Length, length - totalRead); int read = await smtpSession.Connection.ReadBytesAsync(chunk, 0, toRead, token); totalRead += read; await mailStream.WriteAsync(chunk, 0, read, token); } while (totalRead < length); } await mailReference.SaveAsync(token); } await smtpSession.SendReplyAsync(ReplyCode.Okay, $"Recieved {length} octets", token); if (last) { smtpSession.PendingMail = null; await smtpSession.SendReplyAsync(ReplyCode.Okay, "Message complete", token); } }
public SmtpContext(Connection connection, SmtpSession session) { Connection = connection; Session = session; }
public override Task ExecuteAsync(SmtpSession smtpSession, CancellationToken token) { smtpSession.ConnectedHost = Arguments; return(smtpSession.SendReplyAsync(ReplyCode.Okay, $"{smtpSession.Settings.DomainName} greets {Arguments}", token)); }
public override Task ExecuteAsync(SmtpSession smtpSession, CancellationToken token) { smtpSession.PendingMail = null; return(smtpSession.SendReplyAsync(ReplyCode.Okay, token)); }
public override RuleResult Process(MailMessage message, SmtpSession session) { return(RuleResult.None); }
public override async Task ExecuteAsync(SmtpSession smtpSession, CancellationToken token) { await smtpSession.SendReplyAsync(ReplyCode.Greeting, "Ready to start TLS", token); await smtpSession.Connection.NegotiateTlsAsync(); }
public override Task ExecuteAsync(SmtpSession smtpSession, CancellationToken token) { return(smtpSession.SendReplyAsync(ReplyCode.CannotVerify, "Cannot verify", token)); }