private static void Check() { Console.WriteLine("running precheck..."); MongoServer mongoServer = MyMongoDB.GetServer(); MongoDatabase mongoDatabase = mongoServer.GetDatabase("email"); MongoCollection <LazyBsonDocument> mongoCollection = mongoDatabase.GetCollection <LazyBsonDocument>("mails"); MongoCursor <LazyBsonDocument> mongoCursor = mongoCollection.FindAll(); foreach (LazyBsonDocument bsonDocument in mongoCursor) { if (Options.Verbose) { Console.WriteLine("checking email-id: " + bsonDocument["_id"].ToString()); } try { if (User.EMailExists(bsonDocument["RecipientTo"].AsString)) { Console.WriteLine("user with email-address found: " + bsonDocument["RecipientTo"].AsString); User newMailUser = new User(); newMailUser.RefreshById(User.GetIdByEMail(bsonDocument["RecipientTo"].AsString)); eMail mail = new eMail(bsonDocument); mail.AssignToUser(newMailUser); } } catch (Exception ex) { logger.ErrorException(ex.Message, ex); } } Console.WriteLine("precheck finished..."); }
public bool SaveToMongoDB() { if (!this.IsValid) { return(false); } logger.Info("Saving received eMail to Database."); string userDatabase = "email"; if (this._user.IsLoggedIn) { userDatabase = "email_user_" + this._user.Id; } else if (User.EMailExists(this.RecipientTo)) { string userId = User.GetIdByEMail(this.RecipientTo); if (userId != String.Empty) { userDatabase = "email_user_" + userId; } } MongoDatabase mongoDatabase = this._mongoServer.GetDatabase(userDatabase); MongoCollection mongoCollection = mongoDatabase.GetCollection <eMailEntity>("mails"); eMailEntity mailEntity = new eMailEntity { ClientName = this.ClientName, Time = this.Time, MailFrom = this.MailFrom, Subject = this.Subject, RecipientTo = this.RecipientTo, Message = this.Message, HeaderFrom = this.HeaderFrom, HeaderTo = this.HeaderTo, HeaderDate = this.HeaderDate, Folder = this.Folder, RawHeader = this.RawHeader }; if (this.HeaderCc.Count > 0) { mailEntity.HeaderCc = this.HeaderCc; } if (this.HeaderReplyTo != null && this.HeaderReplyTo.Address != String.Empty) { mailEntity.HeaderReplyTo = this.HeaderReplyTo; } try { WriteConcernResult result = mongoCollection.Save(mailEntity, WriteConcern.Acknowledged); return(result.Ok); } catch (Exception e) { Console.WriteLine("MongoCollection.Save Exception: " + e.Message); return(false); } }
public SmtpServer(TcpClient client, int sslPort) : base(client, sslPort) { bool dataStarted = false; string mailMessage = String.Empty; eMail mail = new eMail(); this.Connected += (object sender, TcpRequestEventArgs e) => { if (this.Verbose && e.RemoteEndPoint != null && e.LocalEndPoint != null) { logger.Debug("connected from remote [{0}:{1}] to local [{2}:{3}]", e.RemoteEndPoint.Address.ToString(), e.RemoteEndPoint.Port, e.LocalEndPoint.Address.ToString(), e.LocalEndPoint.Port ); } this.SendMessage("service ready", 220); }; this.Disconnected += (object sender, TcpRequestEventArgs e) => { if (this.Verbose && e.RemoteEndPoint != null && e.LocalEndPoint != null) { logger.Debug("disconnected from remote [{0}:{1}] to local [{2}:{3}]", e.RemoteEndPoint.Address.ToString(), e.RemoteEndPoint.Port, e.LocalEndPoint.Address.ToString(), e.LocalEndPoint.Port ); } }; this.LineReceived += (object sender, TcpLineReceivedEventArgs e) => { logger.Info(String.Format("[{0}:{1}] to [{2}:{3}] Received Line: \"{4}\"", this._remoteEndPoint.Address.ToString(), this._remoteEndPoint.Port, this._localEndPoint.Address.ToString(), this._localEndPoint.Port, e.Line)); switch (this._state) { case State.AuthenticateLoginUsername: this._temporaryVariables["username"] = Encoding.UTF8.GetString(Convert.FromBase64String(e.Line)).Trim(); if (this._temporaryVariables["username"] != String.Empty) { this._state = State.AuthenticateLoginPassword; if (User.NameExists(this._temporaryVariables["username"]) || User.EMailExists(this._temporaryVariables["username"])) { this.SendMessage(Convert.ToBase64String(Encoding.UTF8.GetBytes("Password:"******"5.7.8 Authentication credentials invalid", 535); } } else { this._temporaryVariables.Remove("username"); this._state = State.Default; this.SendMessage("5.7.8 Authentication credentials invalid", 535); } break; case State.AuthenticateLoginPassword: this._temporaryVariables["password"] = Encoding.UTF8.GetString(Convert.FromBase64String(e.Line)).Trim(); this._state = State.Default; if (this._temporaryVariables["password"] != String.Empty) { string username = this._temporaryVariables["username"]; string password = this._temporaryVariables["password"]; this._temporaryVariables.Remove("username"); this._temporaryVariables.Remove("password"); if (this._user.RefreshByUsernamePassword(username, password) || this._user.RefreshByEMailPassword(username, password)) { this.SendMessage("2.7.0 Authentication Succeeded", 235); } else { this.SendMessage("5.7.8 Authentication credentials invalid", 535); } } else { this.SendMessage("5.7.8 Authentication credentials invalid", 535); } break; case State.AuthenticateCramMD5: List <string> wordsCramMD5 = this.GetWordsFromBase64EncodedLine(e.Line); this._state = State.Default; if (wordsCramMD5.Count == 1) { string[] splittedWords = wordsCramMD5[0].Split(new char[] { ' ' }); if (splittedWords.Length == 2) { bool nameExists = User.NameExists(splittedWords[0]); bool eMailExists = User.EMailExists(splittedWords[0]); if (nameExists || eMailExists) { string userId = (nameExists) ? User.GetIdByName(splittedWords[0]) : User.GetIdByEMail(splittedWords[0]); User tmpUser = new User(); if (tmpUser.RefreshById(userId)) { string calculatedDigest = this.CalculateCramMD5Digest(tmpUser.Password, this._currentCramMD5Challenge); if (calculatedDigest == splittedWords[1]) { this._user = tmpUser; this.SendMessage("2.7.0 Authentication Succeeded", 235); } else { this.SendMessage("5.7.8 Authentication credentials invalid", 535); } } else { this.SendMessage("4.7.0 Temporary authentication failure", 454); } } else { this.SendMessage("5.7.8 Authentication credentials invalid", 535); } } else { this.SendMessage("5.7.8 Authentication credentials invalid", 535); } } else { this.SendMessage("5.7.8 Authentication credentials invalid", 535); } this._currentCramMD5Challenge = String.Empty; break; case State.Default: default: if (!dataStarted) { if (e.Line.StartsWith("HELO ")) { mail.SetClientName(e.Line.Substring(5)); this.SendMessage("OK", 250); } else if (e.Line.StartsWith("EHLO ")) { mail.SetClientName(e.Line.Substring(5)); this.SendMessage("Hello " + mail.ClientName + " [" + this._remoteEndPoint.Address.ToString() + "]", "250-localhost"); if (!this.SslIsActive) { string capabilities = "LOGIN"; capabilities += " PLAIN CRAM-MD5"; this.SendMessage(capabilities, "250-AUTH"); this.SendMessage("STARTTLS", 250); } else { string capabilities = "AUTH LOGIN"; capabilities += " PLAIN CRAM-MD5"; this.SendMessage(capabilities, 250); } } else if (e.Line.StartsWith("AUTH ")) { Match authMatch = Regex.Match(e.Line, @"^AUTH\s+(PLAIN|CRAM-MD5|LOGIN)(.*)?", RegexOptions.IgnoreCase); if (authMatch.Success) { switch (authMatch.Groups[1].Value.ToUpper()) { case "PLAIN": List <string> words = new List <string>(); try { words = this.GetWordsFromBase64EncodedLine(authMatch.Groups[2].Value); } catch (Exception) { } this._state = State.Default; if (words.Count == 2) { if (words[0] != String.Empty && words[1] != String.Empty) { if (this._user.RefreshByUsernamePassword(words[0], words[1]) || this._user.RefreshByEMailPassword(words[0], words[1])) { this.SendMessage("2.7.0 Authentication Succeeded", 235); } else { this.SendMessage("5.7.8 Authentication credentials invalid", 535); } } else { this.SendMessage("5.7.8 Authentication credentials invalid", 535); } } else { this.SendMessage("5.7.8 Authentication credentials invalid", 535); } break; case "LOGIN": this._state = State.AuthenticateLoginUsername; this.SendMessage(Convert.ToBase64String(Encoding.UTF8.GetBytes("Username:"******"CRAM-MD5": this._state = State.AuthenticateCramMD5; string base64EncodedCramMD5Challenge = this.CalculateOneTimeBase64Challenge("localhost.de"); this._currentCramMD5Challenge = Encoding.UTF8.GetString(Convert.FromBase64String(base64EncodedCramMD5Challenge)); this.SendMessage(base64EncodedCramMD5Challenge, 334); break; default: this.SendMessage("Unrecognized authentication type", 504); break; } } } else if (e.Line.StartsWith("MAIL FROM:")) { string email = e.Line.Substring(10); try { mail.SetFrom(email); this.SendMessage("OK", 250); } catch (FormatException) { this.SendMessage("BAD <" + email + ">... Denied due to invalid email-format", 555); } } else if (e.Line.StartsWith("RCPT TO:")) { mail.SetRecipient(e.Line.Substring(8)); this.SendMessage("OK", 250); } else if (e.Line.StartsWith("STARTTLS")) { if (e.Line.Trim() == "STARTTLS") { this.SendMessage("Ready to start TLS", 220); if (!this.StartTls()) { this.SendMessage("TLS not available due to temporary reason", 454); } } else { this.SendMessage("Syntax error (no parameters allowed)", 501); } } else if (e.Line == "DATA") { this.SendMessage("start mail input", 354); dataStarted = true; } else if (e.Line == "QUIT") { if (eMailServer.Options.Verbose) { logger.Debug("[{0}:{1}] to [{2}:{3}] quit connection", this._localEndPoint.Address.ToString(), this._localEndPoint.Port, this._remoteEndPoint.Address.ToString(), this._remoteEndPoint.Port); } this.Close(); return; } else { this.SendMessage("Syntax error, command unrecognized", 500); if (eMailServer.Options.Verbose) { logger.Debug("[{0}:{1}] to [{2}:{3}] unknown command: {2}", this._remoteEndPoint.Address.ToString(), this._remoteEndPoint.Port, this._localEndPoint.Address.ToString(), this._localEndPoint.Port, e.Line); } } } else { if (e.Line == ".") { mailMessage = mailMessage.Trim(); logger.Info("[{0}:{1}] to [{2}:{3}] eMail data received: {2}", this._remoteEndPoint.Address.ToString(), this._remoteEndPoint.Port, mailMessage, this._localEndPoint.Address.ToString(), this._localEndPoint.Port); dataStarted = false; mail.ParseData(mailMessage); if (mail.IsValid) { if (this._user.IsLoggedIn && User.EMailExists(mail.MailFrom)) { mail.SetUser(this._user); mail.SetFolder("SENT"); } else { mail.SetFolder("INBOX"); } mail.SaveToMongoDB(); } else { logger.Error("received message is invalid for saving to database."); } this.SendMessage("OK", 250); } else { mailMessage += e.Line + "\r\n"; } } break; } }; }
public ImapServer(TcpClient client, int imapSslPort) : base(client, imapSslPort) { this.Connected += (object sender, TcpRequestEventArgs e) => { if (this.Verbose && e.RemoteEndPoint != null && e.LocalEndPoint != null) { logger.Debug("connected from remote [{0}:{1}] to local [{2}:{3}]", e.RemoteEndPoint.Address.ToString(), e.RemoteEndPoint.Port, e.LocalEndPoint.Address.ToString(), e.LocalEndPoint.Port ); } this.SendMessage("OK IMAP4rev1 Service Ready", "*"); }; this.Disconnected += (object sender, TcpRequestEventArgs e) => { if (this.Verbose && e.RemoteEndPoint != null && e.LocalEndPoint != null) { logger.Debug("disconnected from remote [{0}:{1}] to local [{2}:{3}]", e.RemoteEndPoint.Address.ToString(), e.RemoteEndPoint.Port, e.LocalEndPoint.Address.ToString(), e.LocalEndPoint.Port ); } }; this.LineReceived += (object sender, TcpLineReceivedEventArgs e) => { logger.Info(String.Format("[{0}:{1}] to [{2}:{3}] Received Line: \"{4}\"", this._remoteEndPoint.Address.ToString(), this._remoteEndPoint.Port, this._localEndPoint.Address.ToString(), this._localEndPoint.Port, e.Line)); switch (this._state) { case State.AuthenticateCramMD5: List <string> wordsCramMD5 = this.GetWordsFromBase64EncodedLine(e.Line); this._state = State.Default; if (wordsCramMD5.Count == 1) { string[] splittedWords = wordsCramMD5[0].Split(new char[] { ' ' }); if (splittedWords.Length == 2) { bool nameExists = User.NameExists(splittedWords[0]); bool eMailExists = User.EMailExists(splittedWords[0]); if (nameExists || eMailExists) { string userId = (nameExists) ? User.GetIdByName(splittedWords[0]) : User.GetIdByEMail(splittedWords[0]); User tmpUser = new User(); if (tmpUser.RefreshById(userId)) { string calculatedDigest = this.CalculateCramMD5Digest(tmpUser.Password, this._currentCramMD5Challenge); if (calculatedDigest == splittedWords[1]) { this._user = tmpUser; this.SendMessage("OK PLAIN AUTHENTICATION successful", this._lastClientId); } else { this.SendMessage("NO invalid authentication", this._lastClientId); } } else { this.SendMessage("NO invalid authentication", this._lastClientId); } } else { this.SendMessage("NO invalid authentication", this._lastClientId); } } else { this.SendMessage("NO invalid authentication", this._lastClientId); } } else { this.SendMessage("NO invalid authentication", this._lastClientId); } this._currentCramMD5Challenge = String.Empty; break; case State.AuthenticatePlain: List <string> words = new List <string>(); try { words = this.GetWordsFromBase64EncodedLine(e.Line); } catch (Exception) { // maybe it is not base64-encoded Match plainTextMatch = Regex.Match(e.Line, "\\s+LOGIN\\s+\"([^\"]+)\"\\s+\"([^\"]+)\"", RegexOptions.IgnoreCase); if (plainTextMatch.Success) { words.Add(plainTextMatch.Groups[1].Value); words.Add(plainTextMatch.Groups[2].Value); } } this._state = State.Default; if (words.Count == 2) { if (words[0] != String.Empty && words[1] != String.Empty) { if (this._user.RefreshByUsernamePassword(words[0], words[1]) || this._user.RefreshByEMailPassword(words[0], words[1])) { this.SendMessage("OK PLAIN AUTHENTICATION successful", this._lastClientId); } else { this.SendMessage("NO invalid authentication", this._lastClientId); } } else { this.SendMessage("NO invalid authentication", this._lastClientId); } } else { this.SendMessage("NO invalid authentication", this._lastClientId); } break; case State.Default: Match clientCommandMatch = Regex.Match(e.Line, @"^([^\s]+)\s+(\w+)(\s.+)?", RegexOptions.IgnoreCase); if (clientCommandMatch.Success) { this._lastClientId = clientCommandMatch.Groups[1].Value; switch (clientCommandMatch.Groups[2].Value.ToUpper()) { case "AUTHENTICATE": this.Authenticate(clientCommandMatch.Groups[3].Value.Trim().ToUpper()); break; case "CAPABILITY": string capabilities = "CAPABILITY IMAP4rev1 LOGIN"; if (!this.SslIsActive) { capabilities += " STARTTLS"; } capabilities += " AUTH=PLAIN"; capabilities += " AUTH=CRAM-MD5"; this.SendMessage(capabilities, "*"); this.SendMessage("OK CAPABILITY completed", this._lastClientId); break; case "CHECK": this.SendMessage("OK CHECK completed", this._lastClientId); break; case "FETCH": this.Fetch(); break; case "LOGOUT": this.Logout((TcpRequestHandler.TcpRequestHandler)sender); break; case "NOOP": this.SendMessage("OK NOOP completed", this._lastClientId); break; case "SELECT": this.Select(clientCommandMatch.Groups[3].Value.ToUpper()); break; case "LSUB": Match lsubMatch = Regex.Match(clientCommandMatch.Groups[3].Value, "\"([^\"]*)\"\\s+\"([^\"]*)\"", RegexOptions.Compiled); if (lsubMatch.Success) { List <string> folders = this._user.GetFolders(lsubMatch.Groups[1].Value, lsubMatch.Groups[2].Value); foreach (string folder in folders) { this.SendMessage("LSUB () \"/\" \"" + folder + "\"", "*"); } } this.SendMessage("OK LSUB completed", this._lastClientId); break; case "LIST": this.List(clientCommandMatch.Groups[3].Value.ToUpper()); break; case "STARTTLS": this.SendMessage("OK Begin TLS negotiation now", this._lastClientId); if (this.StartTls()) { this.SendMessage("OK STARTTLS completed", this._lastClientId); } else { this.SendMessage("NO STARTTLS not supported", this._lastClientId); } break; case "UID": this.Uid(clientCommandMatch.Groups[3].Value.Trim()); break; default: this.SendMessage("BAD " + clientCommandMatch.Groups[2].Value + " command not found", this._lastClientId); break; } } else { this.SendMessage("BAD invalid command line: " + e.Line, this._lastClientId); } break; } }; }