mail.cpp

Go to the documentation of this file.
00001 /*
00002  *
00003  * (C) 2003-2013 Anope Team
00004  * Contact us at team@anope.org
00005  *
00006  * Please read COPYING and README for further details.
00007  *
00008  * Based on the original code of Epona by Lara.
00009  * Based on the original code of Services by Andy Church.
00010  *
00011  */
00012 
00013 #include "services.h"
00014 #include "mail.h"
00015 #include "config.h"
00016 
00017 Mail::Message::Message(const Anope::string &sf, const Anope::string &mailto, const Anope::string &a, const Anope::string &s, const Anope::string &m) : Thread(), sendmail_path(Config->SendMailPath), send_from(sf), mail_to(mailto), addr(a), subject(s), message(m), dont_quote_addresses(Config->DontQuoteAddresses), success(false)
00018 {
00019 }
00020 
00021 Mail::Message::~Message()
00022 {
00023         if (success)
00024                 Log(LOG_NORMAL, "mail") << "Successfully delivered mail for " << mail_to << " (" << addr << ")";
00025         else
00026                 Log(LOG_NORMAL, "mail") << "Error delivering mail for " << mail_to << " (" << addr << ")";
00027 }
00028 
00029 void Mail::Message::Run()
00030 {
00031         FILE *pipe = popen(sendmail_path.c_str(), "w");
00032 
00033         if (!pipe)
00034         {
00035                 SetExitState();
00036                 return;
00037         }
00038 
00039         fprintf(pipe, "From: %s\n", send_from.c_str());
00040         if (this->dont_quote_addresses)
00041                 fprintf(pipe, "To: %s <%s>\n", mail_to.c_str(), addr.c_str());
00042         else
00043                 fprintf(pipe, "To: \"%s\" <%s>\n", mail_to.c_str(), addr.c_str());
00044         fprintf(pipe, "Subject: %s\n", subject.c_str());
00045         fprintf(pipe, "%s", message.c_str());
00046         fprintf(pipe, "\n.\n");
00047 
00048         pclose(pipe);
00049 
00050         success = true;
00051         SetExitState();
00052 }
00053 
00054 bool Mail::Send(User *u, NickCore *nc, const BotInfo *service, const Anope::string &subject, const Anope::string &message)
00055 {
00056         if (!nc || !service || subject.empty() || message.empty())
00057                 return false;
00058         
00059         if (!u)
00060         {
00061                 if (!Config->UseMail)
00062                         return false;
00063                 else if (nc->email.empty())
00064                         return false;
00065 
00066                 nc->lastmail = Anope::CurTime;
00067                 Thread *t = new Mail::Message(Config->SendFrom, nc->display, nc->email, subject, message);
00068                 t->Start();
00069                 return true;
00070         }
00071         else
00072         {
00073                 if (!Config->UseMail)
00074                         u->SendMessage(service, _("Services have been configured to not send mail."));
00075                 else if (Anope::CurTime - u->lastmail < Config->MailDelay)
00076                         u->SendMessage(service, _("Please wait \002%d\002 seconds and retry."), Config->MailDelay - (Anope::CurTime - u->lastmail));
00077                 else if (nc->email.empty())
00078                         u->SendMessage(service, _("E-mail for \002%s\002 is invalid."), nc->display.c_str());
00079                 else
00080                 {
00081                         u->lastmail = nc->lastmail = Anope::CurTime;
00082                         Thread *t = new Mail::Message(Config->SendFrom, nc->display, nc->email, subject, message);
00083                         t->Start();
00084                         return true;
00085                 }
00086 
00087                 return false;
00088         }
00089 }
00090 
00091 bool Mail::Send(NickCore *nc, const Anope::string &subject, const Anope::string &message)
00092 {
00093         if (!Config->UseMail || !nc || nc->email.empty() || subject.empty() || message.empty())
00094                 return false;
00095 
00096         nc->lastmail = Anope::CurTime;
00097         Thread *t = new Mail::Message(Config->SendFrom, nc->display, nc->email, subject, message);
00098         t->Start();
00099 
00100         return true;
00101 }
00102 
00112 bool Mail::Validate(const Anope::string &email)
00113 {
00114         bool has_period = false;
00115 
00116         static char specials[] = {'(', ')', '<', '>', '@', ',', ';', ':', '\\', '\"', '[', ']', ' '};
00117 
00118         if (email.empty())
00119                 return false;
00120         Anope::string copy = email;
00121 
00122         size_t at = copy.find('@');
00123         if (at == Anope::string::npos)
00124                 return false;
00125         Anope::string domain = copy.substr(at + 1);
00126         copy = copy.substr(0, at);
00127 
00128         /* Don't accept empty copy or domain. */
00129         if (copy.empty() || domain.empty())
00130                 return false;
00131 
00132         /* Check for forbidden characters in the name */
00133         for (unsigned i = 0, end = copy.length(); i < end; ++i)
00134         {
00135                 if (copy[i] <= 31 || copy[i] >= 127)
00136                         return false;
00137                 for (unsigned int j = 0; j < 13; ++j)
00138                         if (copy[i] == specials[j])
00139                                 return false;
00140         }
00141 
00142         /* Check for forbidden characters in the domain */
00143         for (unsigned i = 0, end = domain.length(); i < end; ++i)
00144         {
00145                 if (domain[i] <= 31 || domain[i] >= 127)
00146                         return false;
00147                 for (unsigned int j = 0; j < 13; ++j)
00148                         if (domain[i] == specials[j])
00149                                 return false;
00150                 if (domain[i] == '.')
00151                 {
00152                         if (!i || i == end - 1)
00153                                 return false;
00154                         has_period = true;
00155                 }
00156         }
00157 
00158         return has_period;
00159 }