def run(self, check=True): import smtplib from MaKaC.webinterface.mail import GenericMailer, GenericNotification # prepare the mail send = self._prepare(check=check) # _prepare decided we shouldn't send the mail? if not send: return addrs = [smtplib.quoteaddr(x) for x in self.toAddr] ccaddrs = [smtplib.quoteaddr(x) for x in self.ccAddr] if len(addrs) + len(ccaddrs) == 0: self.getLogger().warning("Attention: mail contains no recipients!") else: self.getLogger().info("Sending mail To: %s, CC: %s" % (addrs, ccaddrs)) for user in self.toUser: addrs.append(smtplib.quoteaddr(user.getEmail())) GenericMailer.send( GenericNotification( { "fromAddr": self.fromAddr, "toList": addrs, "ccList": ccaddrs, "subject": self.subject, "body": self.text, } ) )
def run(self, check=True): import smtplib from MaKaC.webinterface.mail import GenericMailer, GenericNotification # prepare the mail send = self._prepare(check=check) # _prepare decided we shouldn't send the mail? if not send: return # just in case some ill-behaved code generates empty addresses addrs = list(smtplib.quoteaddr(x) for x in self.toAddr if x) ccaddrs = list(smtplib.quoteaddr(x) for x in self.ccAddr if x) if len(addrs) + len(ccaddrs) == 0: self.getLogger().warning("Attention: no recipients, mail won't be sent") else: self.getLogger().info("Sending mail To: %s, CC: %s" % (addrs, ccaddrs)) for user in self.toUser: addrs.append(smtplib.quoteaddr(user.getEmail())) if addrs or ccaddrs: GenericMailer.send(GenericNotification({"fromAddr": self.fromAddr, "toList": addrs, "ccList": ccaddrs, "subject": self.subject, "body": self.text }))
def run(self): addrs = [] ccaddrs = [] for addr in self.toAddr: addrs.append(smtplib.quoteaddr(addr)) for ccaddr in self.ccAddr: ccaddrs.append(smtplib.quoteaddr(ccaddr)) for user in self.toUser: addrs.append(smtplib.quoteaddr(user.getEmail())) maildata = { "fromAddr": self.fromAddr, "toList": addrs, "ccList": ccaddrs, "subject": self.subject, "body": self.text } GenericMailer.send(GenericNotification(maildata))
def testVRFY(self): smtp = smtplib.SMTP(HOST, self.port, local_hostname='localhost', timeout=15) for email, name in list(sim_users.items()): expected_known = (250, '%s %s' % (name, smtplib.quoteaddr(email))) self.assertEqual(smtp.vrfy(email), expected_known) u = '*****@*****.**' expected_unknown = (550, 'No such user: %s' % smtplib.quoteaddr(u)) self.assertEqual(smtp.vrfy(u), expected_unknown) smtp.quit()
def _sendmail(message=None, debug=False, timeout=10, mongo_settings=None, sleeping=None, smtp_rcpt=None, **kwargs): host, port = utils.get_free_port() with smtp_server(host=host, port=port, mongo_settings=mongo_settings, timeout=timeout, **kwargs) as server: assert server.col.count() == 0 s = smtp_client(host, port, debug=debug) (code, msg) = s.ehlo() assert code == 250 if sleeping: gevent.sleep(sleeping) xforward = { 'ADDR': '192.168.1.1', 'NAME': 'mail.local.net', 'HELO': 'local.net', } (code, msg) = s.docmd('XFORWARD', 'ADDR=%(ADDR)s NAME=%(NAME)s HELO=%(HELO)s' % xforward) assert code == 250 froms = message.get_all('X-Envelope-From', []) if not smtp_rcpt: _recipients = message.get_all('X-Envelope-To', []) recipients = getaddresses(_recipients) else: recipients = [smtp_rcpt] message_string = message.as_string() (code, msg) = s.mail(smtplib.quoteaddr(froms[0]), ["size=%s" % len(message_string)]) assert code == 250 for recipient in recipients: (code, msg) = s.docmd('RCPT TO:', smtplib.quoteaddr(recipient)) assert code == 250 (code, msg) = s.data(message_string) assert code == 250 (code, msg) = s.docmd('quit') assert code == 221 return server
async def mail(self, sender, options=None): """ Sends a SMTP 'MAIL' command. - Starts the mail transfer session. For further details, please check out `RFC 5321 § 4.1.1.2`_ and `§ 3.3`_. Args: sender (str): Sender mailbox (used as reverse-path). options (list of str or None, optional): Additional options to send along with the *MAIL* command. Raises: ConnectionResetError: If the connection with the server is unexpectedely lost. SMTPCommandFailedError: If the MAIL command fails. Returns: (int, str): A (code, message) 2-tuple containing the server response. .. _`RFC 5321 § 4.1.1.2`: https://tools.ietf.org/html/rfc5321#section-4.1.1.2 .. _`§ 3.3`: https://tools.ietf.org/html/rfc5321#section-3.3 """ if options is None: options = [] from_addr = "FROM:{}".format(quoteaddr(sender)) code, message = await self.do_cmd("MAIL", from_addr, *options) return code, message
async def rcpt(self, recipient, options=None): """ Sends a SMTP 'RCPT' command. - Indicates a recipient for the e-mail. For further details, please check out `RFC 5321 § 4.1.1.3`_ and `§ 3.3`_. Args: recipient (str): E-mail address of one recipient. options (list of str or None, optional): Additional options to send along with the *RCPT* command. Raises: ConnectionResetError: If the connection with the server is unexpectedely lost. SMTPCommandFailedError: If the RCPT command fails. Returns: (int, str): A (code, message) 2-tuple containing the server response. .. _`RFC 5321 § 4.1.1.3`: https://tools.ietf.org/html/rfc5321#section-4.1.1.3 .. _`§ 3.3`: https://tools.ietf.org/html/rfc5321#section-3.3 """ if options is None: options = [] to_addr = "TO:{}".format(quoteaddr(recipient)) code, message = await self.do_cmd("RCPT", to_addr, *options) return code, message
def smtp_VRFY(self, arg): raw_addr = email.utils.parseaddr(arg)[1] quoted_addr = smtplib.quoteaddr(arg) if raw_addr in sim_users: self.push('250 %s %s' % (sim_users[raw_addr], quoted_addr)) else: self.push('550 No such user: %s' % arg)
def rcpt(self, recip, options=[]): """SMTP 'rcpt' command -- indicates 1 recipient for this mail.""" optionlist = '' if options and self.does_esmtp: optionlist = ' ' + ' '.join(options) code, msg = yield self.docmd(b"rcpt", ("TO:%s%s" % (smtplib.quoteaddr(recip), optionlist)).encode('ascii')) raise gen.Return((code, msg))
def send_emails(self, from_email, emails, content): """ Use /usr/bin/sendmail or fallback to smtplib. """ if len(emails) == 0: # Nobody to send to - it happens return RETURN_CODES['EX_OK'] try: # This should be secure check: # http://docs.python.org/library/subprocess.html#using-the-subprocess-module # It turns out that sendmail splits the addresses on space, # eventhough there is one address per argument. See RFC5322 section # 3.4 Try: /usr/sbin/sendmail 'soren.roug @eea.europa.eu' and it # will complain about the address. We therefore clean them with # smtplib.quoteaddr quotedemails = map(smtplib.quoteaddr, emails) ps = Popen([self.sendmail_path, '-f', smtplib.quoteaddr(from_email), '--'] + quotedemails, stdin=PIPE) ps.stdin.write(content) ps.stdin.flush() ps.stdin.close() return_code = ps.wait() if return_code in (RETURN_CODES['EX_OK'], RETURN_CODES['EX_TEMPFAIL']): log.debug("Sent emails to %r", emails) return RETURN_CODES['EX_OK'] else: log.error("Failed to send emails using sendmail to %r. " "/usr/sbin/sendmail exited with code %d", emails, return_code) return return_code except OSError: # fallback to smtplib # Since this is the same mailer we use localhost # Smtplib quotes the addresses internally log.exception("Cannot use sendmail program. Falling back to " "smtplib.") log.warning( "If the smtp connection fails some emails will be lost") smtp = smtplib.SMTP('localhost') try: try: smtp.sendmail(from_email, emails, content) log.debug("Sent emails to %r", emails) except smtplib.SMTPException: log.exception("SMTP Error") log.error( "Failed to send emails using smtplib to %r", emails) return RETURN_CODES['EX_PROTOCOL'] except: log.exception("Unknown smtplib error") return RETURN_CODES['EX_UNAVAILABLE'] finally: try: smtp.quit() except: pass return RETURN_CODES['EX_OK']
def testVRFY(self): smtp = smtplib.SMTP(HOST, self.port, local_hostname='localhost', timeout=15) for email, name in sim_users.items(): expected_known = (250, bytes('%s %s' % (name, smtplib.quoteaddr(email)), "ascii")) self.assertEqual(smtp.vrfy(email), expected_known) u = '*****@*****.**' expected_unknown = (550, ('No such user: %s' % smtplib.quoteaddr(u)).encode('ascii')) self.assertEqual(smtp.vrfy(u), expected_unknown) smtp.quit()
def mail(self, sender, options=[]): optionlist = '' if options and self.does_esmtp: optionlist = ' ' + ' '.join(options) (code, msg) = yield self.docmd( b'mail', ('FROM:%s%s' % (smtplib.quoteaddr(sender), optionlist)).encode('ascii')) raise gen.Return((code, msg))
def rcpt(self, recip, options=[]): """SMTP 'rcpt' command -- indicates 1 recipient for this mail.""" optionlist = '' if options and self.does_esmtp: optionlist = ' ' + ' '.join(options) code, msg = yield self.docmd( b"rcpt", ("TO:%s%s" % (smtplib.quoteaddr(recip), optionlist)).encode('ascii')) return (code, msg)
def smtp_VRFY(self, arg): # print '\nsmtp_VRFY(%r)\n' % arg raw_addr = email.utils.parseaddr(arg)[1] quoted_addr = smtplib.quoteaddr(arg) if raw_addr in sim_users: self.push('250 %s %s' % (sim_users[raw_addr], quoted_addr)) else: self.push('550 No such user: %s' % arg)
def testVRFY(self): smtp = smtplib.SMTP(HOST, self.port, local_hostname="localhost", timeout=15) for email, name in sim_users.items(): expected_known = (250, bytes("%s %s" % (name, smtplib.quoteaddr(email)), "ascii")) self.assertEqual(smtp.vrfy(email), expected_known) u = "*****@*****.**" expected_unknown = (550, ("No such user: %s" % u).encode("ascii")) self.assertEqual(smtp.vrfy(u), expected_unknown) smtp.quit()
def validateEmailDomain(toEmail): toDomain = smtplib.quoteaddr(toEmail).split('@')[-1][0:-1] VALIDATED_DOMAINS = ('localhost', 'localhost.localdomain') # basically if we don't implicitly know this domain, # and we can't look up the DNS entry of the MX # use gethostbyname to validate the email address try: if not ((toDomain in VALIDATED_DOMAINS) or digMX(toDomain)): socket.gethostbyname(toDomain) except (socket.gaierror, dns.resolver.NXDOMAIN): raise MailError("Email could not be sent: Bad domain name.")
def smtp_EXPN(self, arg): list_name = arg.lower() if list_name in sim_lists: user_list = sim_lists[list_name] for n, user_email in enumerate(user_list): quoted_addr = smtplib.quoteaddr(user_email) if n < len(user_list) - 1: self.push('250-%s %s' % (sim_users[user_email], quoted_addr)) else: self.push('250 %s %s' % (sim_users[user_email], quoted_addr)) else: self.push('550 No access for you!')
def smtp_EXPN(self, arg): list_name = email.utils.parseaddr(arg)[1].lower() if list_name in sim_lists: user_list = sim_lists[list_name] for n, user_email in enumerate(user_list): quoted_addr = smtplib.quoteaddr(user_email) if n < len(user_list) - 1: self.push("250-%s %s" % (sim_users[user_email], quoted_addr)) else: self.push("250 %s %s" % (sim_users[user_email], quoted_addr)) else: self.push("550 No access for you!")
def testVRFY(self): smtp = smtplib.SMTP(HOST, self.port, local_hostname='localhost', timeout=15) for addr_spec, name in sim_users.items(): expected_known = (250, bytes('%s %s' % (name, smtplib.quoteaddr(addr_spec)), "ascii")) self.assertEqual(smtp.vrfy(addr_spec), expected_known) u = '*****@*****.**' expected_unknown = (550, ('No such user: %s' % u).encode('ascii')) self.assertEqual(smtp.vrfy(u), expected_unknown) smtp.quit()
def testEXPN(self): smtp = smtplib.SMTP(HOST, self.port, local_hostname='localhost', timeout=15) for listname, members in sim_lists.items(): users = [] for m in members: users.append('%s %s' % (sim_users[m], smtplib.quoteaddr(m))) expected_known = (250, bytes('\n'.join(users), "ascii")) self.assertEqual(smtp.expn(listname), expected_known) u = 'PSU-Members-List' expected_unknown = (550, b'No access for you!') self.assertEqual(smtp.expn(u), expected_unknown) smtp.quit()
def testEXPN(self): smtp = smtplib.SMTP(HOST, self.port, local_hostname='localhost', timeout=15) for listname, members in sim_lists.items(): users = [] for m in members: users.append('%s %s' % (sim_users[m], smtplib.quoteaddr(m))) expected_known = (250, '\n'.join(users)) self.assertEqual(smtp.expn(listname), expected_known) u = 'PSU-Members-List' expected_unknown = (550, 'No access for you!') self.assertEqual(smtp.expn(u), expected_unknown) smtp.quit()
def testEXPN(self): smtp = smtplib.SMTP(HOST, self.port, local_hostname="localhost", timeout=15) for listname, members in sim_lists.items(): users = [] for m in members: users.append("%s %s" % (sim_users[m], smtplib.quoteaddr(m))) expected_known = (250, "\n".join(users)) self.assertEqual(smtp.expn(listname), expected_known) u = "PSU-Members-List" expected_unknown = (550, "No access for you!") self.assertEqual(smtp.expn(u), expected_unknown) smtp.quit()
def smtp_EXPN(self, arg): # print '\nsmtp_EXPN(%r)\n' % arg list_name = email.utils.parseaddr(arg)[1].lower() if list_name in sim_lists: user_list = sim_lists[list_name] for n, user_email in enumerate(user_list): quoted_addr = smtplib.quoteaddr(user_email) if n < len(user_list) - 1: self.push('250-%s %s' % (sim_users[user_email], quoted_addr)) else: self.push('250 %s %s' % (sim_users[user_email], quoted_addr)) else: self.push('550 No access for you!')
def _mongodb_verify(message=None, col=None, fs=None, debug=False): froms = message.get_all('X-Envelope-From', []) doc = col.find_one() assert doc['sender'] == smtplib.quoteaddr(froms[0])[1:-1] msg = utils.message_from_string(uncompress(fs.get(doc['message']).read())) if debug: print("") print("------------------------------------------------------------") print(message.as_string()) print("------------------------------------------------------------") return doc, msg
def mail(self, from_addr, options): ''' 一个异步的mail命令,发送mail FROM 发送者地址 ''' # 构造发送命令 send_str = 'mail FROM:{0} {1}'.format( smtplib.quoteaddr(from_addr), b' '.join(options), ).strip().encode('ascii') code, responses = yield self.send(send_str) if code != '250': if code == '421': self.close() else: yield self.rset() raise smtplib.SMTPSenderRefused(code, responses, from_addr) raise gen.Return((code, responses))
def rcpt(self, to_addr, options): ''' 一个异步的rcpt命令,发送rcpt TO 收件者地址 ''' # 构造rcpt命令 rcpt_str = 'rcpt TO:{0} {1}'.format( smtplib.quoteaddr(to_addr), b' '.join(options), ).strip().encode('ascii') code, responses = yield self.send(rcpt_str) if code != '250' and code != '251': if code == '421': self.close() else: yield self.rset() raise smtplib.SMTPSenderRefused(code, responses, to_addr) raise gen.Return((code, responses))
def smtp_VRFY(self, arg): if arg in sim_users: self.push('250 %s %s' % (sim_users[arg], smtplib.quoteaddr(arg))) else: self.push('550 No such user: %s' % arg)
def smtp_VRFY(self, arg): # For max compatibility smtplib should be sending the raw address. if arg in sim_users: self.push('250 %s %s' % (sim_users[arg], smtplib.quoteaddr(arg))) else: self.push('550 No such user: %s' % arg)
def send_emails(self, from_email, emails, content): """ Use /usr/bin/sendmail or fallback to smtplib. """ if len(emails) == 0: # Nobody to send to - it happens return RETURN_CODES['EX_OK'] try: # This should be secure check: # http://docs.python.org/library/subprocess.html # #using-the-subprocess-module # It turns out that sendmail splits the addresses on space, # eventhough there is one address per argument. See RFC5322 section # 3.4 Try: /usr/sbin/sendmail 'test @envcoord.health.fgov.be' and # it will complain about the address. We therefore clean them with # smtplib.quoteaddr quotedemails = map(smtplib.quoteaddr, emails) ps = Popen([ self.sendmail_path, '-f', smtplib.quoteaddr(from_email), '--' ] + quotedemails, stdin=PIPE) ps.stdin.write(content) ps.stdin.flush() ps.stdin.close() return_code = ps.wait() if return_code in (RETURN_CODES['EX_OK'], RETURN_CODES['EX_TEMPFAIL']): log.debug("Sent emails to %r", emails) return RETURN_CODES['EX_OK'] else: log.error( "Failed to send emails using sendmail to %r. " "/usr/sbin/sendmail exited with code %d", emails, return_code) return return_code except OSError: # fallback to smtplib # Since this is the same mailer we use localhost # Smtplib quotes the addresses internally log.exception("Cannot use sendmail program. Falling back to " "smtplib.") log.warning( "If the smtp connection fails some emails will be lost") smtp = smtplib.SMTP('localhost') try: try: smtp.sendmail(from_email, emails, content) log.debug("Sent emails to %r", emails) except smtplib.SMTPException: log.exception("SMTP Error") log.error("Failed to send emails using smtplib to %r", emails) return RETURN_CODES['EX_PROTOCOL'] except Exception as e: log.exception("Smtplib error %s" % e) return RETURN_CODES['EX_UNAVAILABLE'] finally: try: smtp.quit() except Exception: pass return RETURN_CODES['EX_OK']
def mail(self, sender, options=[]): optionlist = '' if options and self.does_esmtp: optionlist = ' ' + ' '.join(options) (code, msg) = yield self.docmd(b'mail', ('FROM:%s%s' % (smtplib.quoteaddr(sender), optionlist)).encode('ascii')) raise gen.Return((code, msg))
def _send(self, message, result): smtp_client = SMTP(source_address=self.source_address, timeout=self.timeout) smtp_client.set_debuglevel(self.debug_level) value = dict(host=self.host, port=self.port) result['connect'] = SMTPCommand("connect", value=value, func=smtp_client.connect, kwargs=value).run() if result['connect']["error"]: raise Exception(result['connect']["error"]) """ TODO: tls if self.tls: (code, msg) = smtp_client.starttls()#keyfile, certfile result['starttls'] = (code, msg) TODO: login if self.login: (code, msg) = smtp_client.login(self.username, self.password) result['login'] = (code, msg) """ value = dict(name=message.get('from_heloname', "helo.example.net")) result['ehlo'] = SMTPCommand("ehlo", value=value["name"], func=smtp_client.ehlo, kwargs=value).run() if result['ehlo']["error"]: raise Exception(result['ehlo']["error"]) features = smtp_client.esmtp_features if self.xclient_enable and "xclient" in features: value = dict(addr=message.get('from_ip'), name=message.get('from_hostname', None), helo=message.get('from_heloname', None)) result['xclient'] = SMTPCommand("xclient", value=value["addr"], func=smtp_client.xclient, kwargs=value).run() if result['xclient']["error"]: raise Exception(result['xclient']["error"]) elif self.xforward_enable and "xforward" in features: value = dict(addr=message.get('from_ip'), name=message.get('from_hostname', None), helo=message.get('from_heloname', None)) result['xforward'] = SMTPCommand("xforward", value=value["addr"], func=smtp_client.xforward, kwargs=value).run() if result['xforward']["error"]: raise Exception(result['xforward']["error"]) value = smtplib.quoteaddr(message['from']) result['mail'] = SMTPCommand("mail", value=message['from'], func=smtp_client.mail, args=[value]).run() if result['mail']["error"]: raise Exception(result['mail']["error"]) recipients_result = [] for recipient in message['tos']: value = smtplib.quoteaddr(recipient) r = SMTPCommand("rcpt", value=recipient, func=smtp_client.rcpt, args=[value]).run() if r["error"]: raise Exception(r["error"]) recipients_result.append(r) result["rcpt"] = recipients_result value = message['message'] result['data'] = SMTPCommand("data", value=value, func=smtp_client.data, args=[value]).run() if result['data']["error"]: raise Exception(result['data']["error"]) """ TODO: avec regexp ou grok, récupérer queue_id selon implémentation server ! """ result['quit'] = SMTPCommand("quit", value=None, func=smtp_client.quit).run() if result['quit']["error"]: raise Exception(result['quit']["error"]) result['success'] = True
def mail(self, sender, options=[]): optionlist = "" if options and self.does_esmtp: optionlist = " " + " ".join(options) (code, msg) = yield self.docmd(b"mail", ("FROM:%s%s" % (smtplib.quoteaddr(sender), optionlist)).encode("ascii")) return (code, msg)
def rcpt(self, recip, options=[]): optionlist = '' if options and self.does_esmtp: optionlist = ' ' + string.join(options, ' ') self.putcmd('rcpt', 'TO:%s%s' % (smtplib.quoteaddr(recip), optionlist)) return self.getreply()
def update_event(self, inp=-1): self.set_output_val(0, smtplib.quoteaddr(self.input(0)))
def mail(self, sender, options=[]): optionlist = '' if options and self.does_esmtp: optionlist = ' ' + string.join(options, ' ') self.putcmd('mail', 'FROM:%s%s' % (smtplib.quoteaddr(sender), optionlist)) return self.getreply()