public void InsertEmail(UUID to, Email email) { // It's tempting to create the queue here. Don't; objects which have // not yet called GetNextEmail should have no queue, and emails to them // should be silently dropped. lock (m_MailQueues) { if (m_MailQueues.ContainsKey(to)) { if (m_MailQueues[to].Count >= m_MaxQueueSize) { // fail silently return; } lock (m_MailQueues[to]) { m_MailQueues[to].Add(email); } } } }
private Email QueryNextEmail(ISimpleDB db, UUID uuid, string sender, string subject) { Email msg = new Email(); try { Dictionary<string, object> parms = new Dictionary<string, object>(); string query = "SELECT * FROM emailmessages WHERE uuid = ?uuid"; parms.Add("?uuid", uuid); if (!String.IsNullOrEmpty(sender)) { query += " AND from = ?from"; parms.Add("?from", sender); } if (!String.IsNullOrEmpty(subject)) { query += " AND subject = ?subject"; parms.Add("?subject", subject); } query += " ORDER BY sent LIMIT 1"; List<Dictionary<string, string>> results = db.QueryWithResults(query, parms); if (results.Count != 1) return null; uint ID = Convert.ToUInt32(results[0]["ID"]); uint unixtime = Convert.ToUInt32(results[0]["sent"]); msg.time = unixtime.ToString(); // Note: email event is documented as string form of *UTC* unix time msg.sender = results[0]["from"]; msg.subject = results[0]["subject"]; msg.message = results[0]["body"]; // This one has been handled, remove it from those queued in the DB. DeleteMessage(db, ID); } catch (Exception e) { m_log.Error("[InboundEmail]: Exception during database call to store message: " + e.Message); m_log.Error(e.StackTrace); return null; } msg.numLeft = (int)QueryEmailCount(db, uuid); return msg; }
/// <summary> /// SendMail function utilized by llEMail /// </summary> /// <param name="objectID"></param> /// <param name="address"></param> /// <param name="subject"></param> /// <param name="body"></param> public void SendEmail(UUID objectID, string address, string subject, string body) { //Check if address is empty if (address == string.Empty) return; //FIXED:Check the email is correct form in REGEX string EMailpatternStrict = @"^(([^<>()[\]\\.,;:\s@\""]+" + @"(\.[^<>()[\]\\.,;:\s@\""]+)*)|(\"".+\""))@" + @"((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}" + @"\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+" + @"[a-zA-Z]{2,}))$"; Regex EMailreStrict = new Regex(EMailpatternStrict); bool isEMailStrictMatch = EMailreStrict.IsMatch(address); if (!isEMailStrictMatch) { m_log.Error("[EMAIL] REGEX Problem in EMail Address: "+address); return; } if ((subject.Length + body.Length) > m_MaxEmailSize) { m_log.Error("[EMAIL] subject + body larger than limit of " + m_MaxEmailSize + " bytes"); return; } string LastObjectName = string.Empty; string LastObjectPosition = string.Empty; string LastObjectRegionName = string.Empty; resolveNamePositionRegionName(objectID, out LastObjectName, out LastObjectPosition, out LastObjectRegionName); if (!address.EndsWith(m_InterObjectHostname)) { // regular email, send it out try { //Creation EmailMessage EmailMessage emailMessage = new EmailMessage(); //From emailMessage.FromAddress = new EmailAddress(objectID.ToString() + "@" + m_HostName); //To - Only One emailMessage.AddToAddress(new EmailAddress(address)); //Subject emailMessage.Subject = subject; //TEXT Body resolveNamePositionRegionName(objectID, out LastObjectName, out LastObjectPosition, out LastObjectRegionName); emailMessage.BodyText = "Object-Name: " + LastObjectName + "\nRegion: " + LastObjectRegionName + "\nLocal-Position: " + LastObjectPosition + "\n\n" + body; //Config SMTP Server //Set SMTP SERVER config SmtpServer smtpServer=new SmtpServer(SMTP_SERVER_HOSTNAME,SMTP_SERVER_PORT); // Add authentication only when requested // if (SMTP_SERVER_LOGIN != String.Empty && SMTP_SERVER_PASSWORD != String.Empty) { //Authentication smtpServer.SmtpAuthToken=new SmtpAuthToken(SMTP_SERVER_LOGIN, SMTP_SERVER_PASSWORD); } //Send Email Message emailMessage.Send(smtpServer); //Log m_log.Info("[EMAIL] EMail sent to: " + address + " from object: " + objectID.ToString() + "@" + m_HostName); } catch (Exception e) { m_log.Error("[EMAIL] DefaultEmailModule Exception: " + e.Message); } } else { // inter object email, keep it in the family Email email = new Email(); email.time = ((int)((DateTime.UtcNow - new DateTime(1970,1,1,0,0,0)).TotalSeconds)).ToString(); email.subject = subject; email.sender = objectID.ToString() + "@" + m_InterObjectHostname; email.message = "Object-Name: " + LastObjectName + "\nRegion: " + LastObjectRegionName + "\nLocal-Position: " + LastObjectPosition + "\n\n" + body; string guid = address.Substring(0, address.IndexOf("@")); UUID toID = new UUID(guid); if (IsLocal(toID)) // TODO FIX check to see if it is local { // object in this region InsertEmail(toID, email); } else { // object on another region // TODO FIX } } }
public Email GetNextEmail(UUID objectID, string sender, string subject) { string m_Object; string num_emails = ""; m_Object = objectID + "@" + m_HostName; Hashtable ReqHash = new Hashtable(); ReqHash["objectid"] = m_Object; Hashtable result = GenericXMLRPCRequest(ReqHash, "check_email"); if (!Convert.ToBoolean(result["success"])) { return null; } ArrayList dataArray = (ArrayList)result["data"]; foreach (Object o in dataArray) { Hashtable d = (Hashtable)o; num_emails = d["num_emails"].ToString(); } //m_log.Error("[OPENEMAIL] " + num_emails); DelayInSeconds(2); if(num_emails != "0") { // Get the info from the database and Queue it up Hashtable GetHash = new Hashtable(); GetHash["objectid"] = m_Object; GetHash["number"] = num_emails; //m_log.Debug("[OPENEMAIL] I have " + num_emails + " waiting on dataserver"); Hashtable results = GenericXMLRPCRequest(GetHash, "retrieve_email"); if (!Convert.ToBoolean(results["success"])) { return null; } ArrayList mailArray = (ArrayList)results["data"]; foreach (Object ob in mailArray) { Hashtable d = (Hashtable)ob; Email email = new Email(); // Debugging //m_log.Debug("[OPENEMAIL] Time: " + d["timestamp"].ToString()); //m_log.Debug("[OPENEMAIL] Subject: " + d["subject"].ToString()); //m_log.Debug("[OPENEMAIL] Sender: " + d["sender"].ToString()); //m_log.Debug("[OPENEMAIL] Object: " + d["objectname"].ToString()); //m_log.Debug("[OPENEMAIL] Region: " + d["region"].ToString()); //m_log.Debug("[OPENEMAIL] Local-Position: " + d["objectpos"].ToString()); //m_log.Debug("[OPENEMAIL] Message: " + d["message"].ToString()); email.time = d["timestamp"].ToString(); email.subject = d["subject"].ToString(); email.sender = d["sender"].ToString(); email.message = "Object-Name: " + d["objectname"].ToString() + "\nRegion: " + d["region"].ToString() + "\nLocal-Position: " + d["objectpos"].ToString() + "\n\n" + d["message"].ToString(); string guid = m_Object.Substring(0, m_Object.IndexOf("@")); UUID toID = new UUID(guid); InsertEmail(toID, email); } } // And let's start with readin the Queue here List<Email> queue = null; lock (m_LastGetEmailCall) { if (m_LastGetEmailCall.ContainsKey(objectID)) { m_LastGetEmailCall.Remove(objectID); } m_LastGetEmailCall.Add(objectID, DateTime.Now); // Hopefully this isn't too time consuming. If it is, we can always push it into a worker thread. DateTime now = DateTime.Now; List<UUID> removal = new List<UUID>(); foreach (UUID uuid in m_LastGetEmailCall.Keys) { if ((now - m_LastGetEmailCall[uuid]) > m_QueueTimeout) { removal.Add(uuid); } } foreach (UUID remove in removal) { m_LastGetEmailCall.Remove(remove); lock (m_MailQueues) { m_MailQueues.Remove(remove); } } } lock (m_MailQueues) { if (m_MailQueues.ContainsKey(objectID)) { queue = m_MailQueues[objectID]; } } if (queue != null) { lock (queue) { if (queue.Count > 0) { int i; for (i = 0; i < queue.Count; i++) { if ((sender == null || sender.Equals("") || sender.Equals(queue[i].sender)) && (subject == null || subject.Equals("") || subject.Equals(queue[i].subject))) { break; } } if (i != queue.Count) { Email ret = queue[i]; queue.Remove(ret); ret.numLeft = queue.Count; return ret; } } } } else { lock (m_MailQueues) { m_MailQueues.Add(objectID, new List<Email>()); } } return null; }
/// <summary> /// SendMail function utilized by llEMail /// </summary> /// <param name="objectID"></param> /// <param name="address"></param> /// <param name="subject"></param> /// <param name="body"></param> public void SendEmail(UUID objectID, string address, string subject, string body) { //Check if address is empty if (address == string.Empty) return; //FIXED:Check the email is correct form in REGEX string EMailpatternStrict = @"^(([^<>()[\]\\.,;:\s@\""]+" + @"(\.[^<>()[\]\\.,;:\s@\""]+)*)|(\"".+\""))@" + @"((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}" + @"\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+" + @"[a-zA-Z]{2,}))$"; Regex EMailreStrict = new Regex(EMailpatternStrict); bool isEMailStrictMatch = EMailreStrict.IsMatch(address); if (!isEMailStrictMatch) { m_log.Error("[EMAIL] REGEX Problem in EMail Address: "+address); return; } //FIXME:Check if subject + body = 4096 Byte if ((subject.Length + body.Length) > 1024) { m_log.Error("[EMAIL] subject + body > 1024 Byte"); return; } string LastObjectName = string.Empty; string LastObjectPosition = string.Empty; string LastObjectRegionName = string.Empty; resolveNamePositionRegionName(objectID, out LastObjectName, out LastObjectPosition, out LastObjectRegionName); if (!address.EndsWith(m_InterObjectHostname)) { if (!m_localOnly) { string m_ObjectRegionName; SceneObjectPart part = findPrim(objectID, out m_ObjectRegionName); if (part != null) { lock (m_Scenes) { foreach (Scene s in m_Scenes.Values) { ScenePresence SP = s.GetScenePresence(part.OwnerID); if (SP != null) { if (!SP.IsChildAgent) SP.ControllingClient.SendAlertMessage("llEmail: email module not configured for outgoing emails"); } } } } } // regular email, send it out try { //Creation EmailMessage EmailMessage emailMessage = new EmailMessage(); //From emailMessage.FromAddress = new EmailAddress(objectID.ToString() + "@" + m_HostName); //To - Only One emailMessage.AddToAddress(new EmailAddress(address)); //Subject emailMessage.Subject = subject; //TEXT Body resolveNamePositionRegionName(objectID, out LastObjectName, out LastObjectPosition, out LastObjectRegionName); emailMessage.BodyText = "Object-Name: " + LastObjectName + "\nRegion: " + LastObjectRegionName + "\nLocal-Position: " + LastObjectPosition + "\n\n" + body; //Config SMTP Server //Set SMTP SERVER config SmtpServer smtpServer=new SmtpServer(SMTP_SERVER_HOSTNAME,SMTP_SERVER_PORT); // Add authentication only when requested // if (SMTP_SERVER_LOGIN != String.Empty && SMTP_SERVER_PASSWORD != String.Empty) { //Authentication smtpServer.SmtpAuthToken=new SmtpAuthToken(SMTP_SERVER_LOGIN, SMTP_SERVER_PASSWORD); } //Send Email Message emailMessage.Send(smtpServer); //Log m_log.Info("[EMAIL] EMail sent to: " + address + " from object: " + objectID.ToString() + "@" + m_HostName); } catch (Exception e) { m_log.Error("[EMAIL] DefaultEmailModule Exception: " + e.Message); } } else { // inter object email, keep it in the family Email email = new Email(); email.time = ((int)((DateTime.UtcNow - new DateTime(1970,1,1,0,0,0)).TotalSeconds)).ToString(); email.subject = subject; email.sender = objectID.ToString() + "@" + m_InterObjectHostname; email.message = "Object-Name: " + LastObjectName + "\nRegion: " + LastObjectRegionName + "\nLocal-Position: " + LastObjectPosition + "\n\n" + body; string guid = address.Substring(0, address.IndexOf("@")); UUID toID = new UUID(guid); if (IsLocal(toID)) { // object in this region InsertEmail(toID, email); } else { // object on another region //This should be dealt with by other modules, not us } } //DONE: Message as Second Life style //20 second delay - AntiSpam System - for now only 10 seconds DelayInSeconds(10); }
public void InsertEmail(UUID to, Email email) { // It's tempting to create the queue here. Don't; objects which have // not yet called GetNextEmail should have no queue, and emails to them // should be silently dropped. EmailQueue val; if(m_MailQueues.TryGetValue(to, out val)) { if (val.m_Queue.Count >= m_MaxQueueSize) { // fail silently return; } val.m_LastCall = DateTime.Now; val.m_Queue.Add(email); } }