anope- supernets anope source code & configuration |
git clone git://git.acid.vegas/anope.git |
Log | Files | Refs | Archive | README |
mail.cpp (4851B)
1 /* 2 * 3 * (C) 2003-2022 Anope Team 4 * Contact us at team@anope.org 5 * 6 * Please read COPYING and README for further details. 7 * 8 * Based on the original code of Epona by Lara. 9 * Based on the original code of Services by Andy Church. 10 */ 11 12 #include "services.h" 13 #include "mail.h" 14 #include "config.h" 15 16 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->GetBlock("mail")->Get<const Anope::string>("sendmailpath")), send_from(sf), mail_to(mailto), addr(a), subject(s), message(m), dont_quote_addresses(Config->GetBlock("mail")->Get<bool>("dontquoteaddresses")), success(false) 17 { 18 } 19 20 Mail::Message::~Message() 21 { 22 if (success) 23 Log(LOG_NORMAL, "mail") << "Successfully delivered mail for " << mail_to << " (" << addr << ")"; 24 else 25 Log(LOG_NORMAL, "mail") << "Error delivering mail for " << mail_to << " (" << addr << ")"; 26 } 27 28 void Mail::Message::Run() 29 { 30 FILE *pipe = popen(sendmail_path.c_str(), "w"); 31 32 if (!pipe) 33 { 34 SetExitState(); 35 return; 36 } 37 38 fprintf(pipe, "From: %s\n", send_from.c_str()); 39 if (this->dont_quote_addresses) 40 fprintf(pipe, "To: %s <%s>\n", mail_to.c_str(), addr.c_str()); 41 else 42 fprintf(pipe, "To: \"%s\" <%s>\n", mail_to.c_str(), addr.c_str()); 43 fprintf(pipe, "Subject: %s\n", subject.c_str()); 44 fprintf(pipe, "Content-Type: text/plain; charset=UTF-8;\n"); 45 fprintf(pipe, "Content-Transfer-Encoding: 8bit\n"); 46 fprintf(pipe, "\n"); 47 fprintf(pipe, "%s", message.c_str()); 48 fprintf(pipe, "\n.\n"); 49 50 pclose(pipe); 51 52 success = true; 53 SetExitState(); 54 } 55 56 bool Mail::Send(User *u, NickCore *nc, BotInfo *service, const Anope::string &subject, const Anope::string &message) 57 { 58 if (!nc || !service || subject.empty() || message.empty()) 59 return false; 60 61 Configuration::Block *b = Config->GetBlock("mail"); 62 63 if (!u) 64 { 65 if (!b->Get<bool>("usemail") || b->Get<const Anope::string>("sendfrom").empty()) 66 return false; 67 else if (nc->email.empty()) 68 return false; 69 70 nc->lastmail = Anope::CurTime; 71 Thread *t = new Mail::Message(b->Get<const Anope::string>("sendfrom"), nc->display, nc->email, subject, message); 72 t->Start(); 73 return true; 74 } 75 else 76 { 77 if (!b->Get<bool>("usemail") || b->Get<const Anope::string>("sendfrom").empty()) 78 u->SendMessage(service, _("Services have been configured to not send mail.")); 79 else if (Anope::CurTime - u->lastmail < b->Get<time_t>("delay")) 80 u->SendMessage(service, _("Please wait \002%d\002 seconds and retry."), b->Get<time_t>("delay") - (Anope::CurTime - u->lastmail)); 81 else if (nc->email.empty()) 82 u->SendMessage(service, _("E-mail for \002%s\002 is invalid."), nc->display.c_str()); 83 else 84 { 85 u->lastmail = nc->lastmail = Anope::CurTime; 86 Thread *t = new Mail::Message(b->Get<const Anope::string>("sendfrom"), nc->display, nc->email, subject, message); 87 t->Start(); 88 return true; 89 } 90 91 return false; 92 } 93 } 94 95 bool Mail::Send(NickCore *nc, const Anope::string &subject, const Anope::string &message) 96 { 97 Configuration::Block *b = Config->GetBlock("mail"); 98 if (!b->Get<bool>("usemail") || b->Get<const Anope::string>("sendfrom").empty() || !nc || nc->email.empty() || subject.empty() || message.empty()) 99 return false; 100 101 nc->lastmail = Anope::CurTime; 102 Thread *t = new Mail::Message(b->Get<const Anope::string>("sendfrom"), nc->display, nc->email, subject, message); 103 t->Start(); 104 105 return true; 106 } 107 108 /** 109 * Checks whether we have a valid, common e-mail address. 110 * This is NOT entirely RFC compliant, and won't be so, because I said 111 * *common* cases. ;) It is very unlikely that e-mail addresses that 112 * are really being used will fail the check. 113 * 114 * @param email Email to Validate 115 * @return bool 116 */ 117 bool Mail::Validate(const Anope::string &email) 118 { 119 bool has_period = false; 120 121 static char specials[] = {'(', ')', '<', '>', '@', ',', ';', ':', '\\', '\"', '[', ']', ' '}; 122 123 if (email.empty()) 124 return false; 125 Anope::string copy = email; 126 127 size_t at = copy.find('@'); 128 if (at == Anope::string::npos) 129 return false; 130 Anope::string domain = copy.substr(at + 1); 131 copy = copy.substr(0, at); 132 133 /* Don't accept empty copy or domain. */ 134 if (copy.empty() || domain.empty()) 135 return false; 136 137 /* Check for forbidden characters in the name */ 138 for (unsigned i = 0, end = copy.length(); i < end; ++i) 139 { 140 if (copy[i] <= 31 || copy[i] >= 127) 141 return false; 142 for (unsigned int j = 0; j < 13; ++j) 143 if (copy[i] == specials[j]) 144 return false; 145 } 146 147 /* Check for forbidden characters in the domain */ 148 for (unsigned i = 0, end = domain.length(); i < end; ++i) 149 { 150 if (domain[i] <= 31 || domain[i] >= 127) 151 return false; 152 for (unsigned int j = 0; j < 13; ++j) 153 if (domain[i] == specials[j]) 154 return false; 155 if (domain[i] == '.') 156 { 157 if (!i || i == end - 1) 158 return false; 159 has_period = true; 160 } 161 } 162 163 return has_period; 164 }