def sendmail_send(recipient, message, config=None, section='DEFAULT'): if config is None: config = _config.CONFIG message_bytes = _flatten(message) sendmail = [config.get(section, 'sendmail')] sendmail_config = config.get(section, 'sendmail_config') if sendmail_config: sendmail.extend(['-C', sendmail_config]) sender_name, sender_addr = _parseaddr(config.get(section, 'from')) _LOG.debug('sending message to {} via {}'.format(recipient, sendmail)) try: p = _subprocess.Popen( sendmail + ['-F', sender_name, '-f', sender_addr, recipient], stdin=_subprocess.PIPE, stdout=_subprocess.PIPE, stderr=_subprocess.STDOUT) stdout, _ = p.communicate(message_bytes) status = p.wait() _LOG.debug(stdout.decode()) if status: if _LOG.level > logging.DEBUG: _LOG.error(stdout.decode()) raise _error.SendmailError(status=status) except Exception as e: raise _error.SendmailError() from e
def validate_email_address(email_id: str) -> str: if not email_id: raise AppException("Invalid email") email_id = email_id.lower() if "@" in _parseaddr(email_id)[1]: return email_id raise AppException("Invalid Email", HTTPStatus.BAD_REQUEST)
def get_message(sender, recipient, subject, body, content_type="plain", extra_headers=None): """Generate a `Message` instance. All arguments should be Unicode strings (plain ASCII works as well). Only the real name part of sender and recipient addresses may contain non-ASCII characters. The email will be properly MIME encoded. The charset of the email will be the first one out of the list that can represent all the characters occurring in the email. """ # Split real name (which is optional) and email address parts sender_name, sender_addr = _parseaddr(sender) recipient_name, recipient_addr = _parseaddr(recipient) sender_encoding = guess_encoding(sender_name) recipient_encoding = guess_encoding(recipient_name) subject_encoding = guess_encoding(subject) body_encoding = guess_encoding(body) # We must always pass Unicode strings to Header, otherwise it will # use RFC 2047 encoding even on plain ASCII strings. sender_name = str(_Header(sender_name, sender_encoding).encode()) recipient_name = str(_Header(recipient_name, recipient_encoding).encode()) # Make sure email addresses do not contain non-ASCII characters sender_addr.encode('ascii') recipient_addr.encode('ascii') # Create the message ('plain' stands for Content-Type: text/plain) message = _MIMEText(body, content_type, body_encoding) message['From'] = _formataddr((sender_name, sender_addr)) message['To'] = _formataddr((recipient_name, recipient_addr)) message['Subject'] = _Header(subject, subject_encoding) if extra_headers: for key, value in extra_headers.items(): encoding = guess_encoding(value) message[key] = _Header(value, encoding) return message
def _new_digest(self): digest = _MIMEMultipart('digest') digest['To'] = _formataddr(_parseaddr(self.to)) # Encodes with utf-8 as necessary digest['Subject'] = 'digest for {}'.format(self.name) digest['Message-ID'] = '<{0}@{1}>'.format(_uuid.uuid4(), platform.node()) digest['User-Agent'] = self.user_agent digest['List-ID'] = '<{}.localhost>'.format(self.name) digest['List-Post'] = 'NO (posting not allowed on this list)' digest['X-RSS-Feed'] = self.url return digest
def sendmail_send(sender, recipient, message, config=None, section='DEFAULT'): if config is None: config = _config.CONFIG message_bytes = _flatten(message) sendmail = config.get(section, 'sendmail') sender_name,sender_addr = _parseaddr(sender) _LOG.debug( 'sending message to {} via {}'.format(recipient, sendmail)) try: p = _subprocess.Popen( [sendmail, '-F', sender_name, '-f', sender_addr, recipient], stdin=_subprocess.PIPE, stdout=_subprocess.PIPE, stderr=_subprocess.PIPE) stdout,stderr = p.communicate(message_bytes) status = p.wait() if status: raise _error.SendmailError( status=status, stdout=stdout, stderr=stderr) except Exception as e: raise _error.SendmailError() from e
"Catalyst is the release building tool used by Gentoo Linux" import codecs as _codecs from distutils.core import setup as _setup from email.utils import parseaddr as _parseaddr import itertools as _itertools import os as _os from catalyst import __version__, __maintainer__ _this_dir = _os.path.dirname(__file__) _package_name = 'catalyst' _maintainer_name, _maintainer_email = _parseaddr(__maintainer__) def _posix_path(path): """Convert a native path to a POSIX path Distutils wants all paths to be written in the Unix convention (i.e. slash-separated) [1], so that's what we'll do here. [1]: http://docs.python.org/2/distutils/setupscript.html#writing-the-setup-script """ if _os.path.sep != '/': return path.replace(_os.path.sep, '/') return path def _files(prefix, root): """Iterate through all the file paths under `root`
def get_message(sender, recipient, subject, body, content_type, extra_headers=None, config=None, section='DEFAULT'): """Generate a `Message` instance. All arguments should be Unicode strings (plain ASCII works as well). Only the real name part of sender and recipient addresses may contain non-ASCII characters. The email will be properly MIME encoded. The charset of the email will be the first one out of the list that can represent all the characters occurring in the email. >>> message = get_message( ... sender='John <*****@*****.**>', recipient='Ζεύς <*****@*****.**>', ... subject='Testing', ... body='Hello, world!\\n', ... content_type='plain', ... extra_headers={'Approved': '*****@*****.**'}) >>> print(message.as_string()) # doctest: +REPORT_UDIFF MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit From: John <*****@*****.**> To: =?utf-8?b?zpbOtc+Nz4I=?= <*****@*****.**> Subject: Testing Approved: [email protected] <BLANKLINE> Hello, world! <BLANKLINE> """ if config is None: config = _config.CONFIG if section not in config.sections(): section = 'DEFAULT' encodings = [ x.strip() for x in config.get(section, 'encodings').split(',')] # Split real name (which is optional) and email address parts sender_name,sender_addr = _parseaddr(sender) recipient_name,recipient_addr = _parseaddr(recipient) sender_encoding = guess_encoding(sender_name, encodings) recipient_encoding = guess_encoding(recipient_name, encodings) subject_encoding = guess_encoding(subject, encodings) body_encoding = guess_encoding(body, encodings) # We must always pass Unicode strings to Header, otherwise it will # use RFC 2047 encoding even on plain ASCII strings. sender_name = str(_Header(sender_name, sender_encoding).encode()) recipient_name = str(_Header(recipient_name, recipient_encoding).encode()) # Make sure email addresses do not contain non-ASCII characters sender_addr.encode('ascii') recipient_addr.encode('ascii') # Create the message ('plain' stands for Content-Type: text/plain) message = _MIMEText(body, content_type, body_encoding) message['From'] = _formataddr((sender_name, sender_addr)) message['To'] = _formataddr((recipient_name, recipient_addr)) message['Subject'] = _Header(subject, subject_encoding) if config.getboolean(section, 'use-8bit'): del message['Content-Transfer-Encoding'] charset = _Charset(body_encoding) charset.body_encoding = _email_encoders.encode_7or8bit message.set_payload(body, charset=charset) if extra_headers: for key,value in extra_headers.items(): encoding = guess_encoding(value, encodings) message[key] = _Header(value, encoding) return message
def get_message(sender, recipient, subject, body, content_type, extra_headers=None, config=None, section='DEFAULT'): """Generate a `Message` instance. All arguments should be Unicode strings (plain ASCII works as well). Only the real name part of sender and recipient addresses may contain non-ASCII characters. The email will be properly MIME encoded. The charset of the email will be the first one out of the list that can represent all the characters occurring in the email. >>> message = get_message( ... sender='John <*****@*****.**>', recipient='Ζεύς <*****@*****.**>', ... subject='Testing', ... body='Hello, world!\\n', ... content_type='plain', ... extra_headers={'Approved': '*****@*****.**'}) >>> print(message.as_string()) # doctest: +REPORT_UDIFF MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit From: John <*****@*****.**> To: =?utf-8?b?zpbOtc+Nz4I=?= <*****@*****.**> Subject: Testing Approved: [email protected] <BLANKLINE> Hello, world! <BLANKLINE> """ if config is None: config = _config.CONFIG if section not in config.sections(): section = 'DEFAULT' encodings = [ x.strip() for x in config.get(section, 'encodings').split(',') ] # Split real name (which is optional) and email address parts sender_name, sender_addr = _parseaddr(sender) recipient_list = [] for recipient_name, recipient_addr in _getaddresses([recipient]): recipient_encoding = guess_encoding(recipient_name, encodings) recipient_name = str( _Header(recipient_name, recipient_encoding).encode()) recipient_addr.encode('ascii') recipient_list.append(_formataddr((recipient_name, recipient_addr))) sender_encoding = guess_encoding(sender_name, encodings) recipient_encoding = guess_encoding(recipient_name, encodings) subject_encoding = guess_encoding(subject, encodings) body_encoding = guess_encoding(body, encodings) # We must always pass Unicode strings to Header, otherwise it will # use RFC 2047 encoding even on plain ASCII strings. sender_name = str(_Header(sender_name, sender_encoding).encode()) # Make sure email addresses do not contain non-ASCII characters sender_addr.encode('ascii') # Create the message ('plain' stands for Content-Type: text/plain) message = _MIMEText(body, content_type, body_encoding) message['From'] = _formataddr((sender_name, sender_addr)) message['To'] = ', '.join(recipient_list) message['Subject'] = _Header(subject, subject_encoding) if config.getboolean(section, 'use-8bit'): del message['Content-Transfer-Encoding'] charset = _Charset(body_encoding) charset.body_encoding = _email_encoders.encode_7or8bit message.set_payload(body, charset=charset) if extra_headers: for key, value in extra_headers.items(): encoding = guess_encoding(value, encodings) message[key] = _Header(value, encoding) return message
def _get_message_person(course, message, trust_admin_from=True): """Get the `Person` that sent the message. We use 'Return-Path' (envelope from) instead of the message's From header, because it's more consistent and harder to fake. However, there may be times when you *want* to send a message in somebody elses name. For example, if a student submitted an assignment from an unexpected address, you might add that address to their entry in your course config, and then bounce the message back into pygrader. In this case, the From header will still be the student, but the 'Return-Path' will be you. With `trust_admin_from` (on by default), messages who's 'Return-Path' matches a professor or TA will have their 'From' line used to find the final person responsible for the message. >>> from pygrader.model.course import Course >>> from pygrader.model.person import Person >>> from pgp_mime import encodedMIMEText >>> course = Course(people=[ ... Person( ... name='Gandalf', emails=['*****@*****.**'], groups=['professors']), ... Person(name='Bilbo', emails=['*****@*****.**']), ... ]) >>> message = encodedMIMEText('testing') >>> message['Return-Path'] = '<*****@*****.**>' >>> message['From'] = 'Bill <*****@*****.**>' >>> message['Message-ID'] = '<*****@*****.**>' >>> person = _get_message_person(course=course, message=message) >>> print(person) <Person Bilbo> >>> person = _get_message_person( ... course=course, message=message, trust_admin_from=False) >>> print(person) <Person Gandalf> """ sender = message['return-path'] # RFC 822 if sender is None: raise NoReturnPath(message) sender = sender[1:-1] # strip wrapping '<' and '>' people = list(course.find_people(email=sender)) if len(people) == 0: raise UnregisteredAddress(message=message, address=sender) if len(people) > 1: raise AmbiguousAddress(message=message, address=sender, people=people) person = people[0] if trust_admin_from and person.is_admin(): mid = message['message-id'] from_headers = message.get_all('from') if len(from_headers) == 0: _LOG.debug("no 'From' headers in {}".format(mid)) elif len(from_headers) > 1: _LOG.debug("multiple 'From' headers in {}".format(mid)) else: name,address = _parseaddr(from_headers[0]) people = list(course.find_people(email=address)) if len(people) == 0: _LOG.debug("'From' address {} is unregistered".format(address)) if len(people) > 1: _LOG.debug("'From' address {} is ambiguous".format(address)) _LOG.debug('message from {} treated as being from {}'.format( person, people[0])) person = people[0] _LOG.debug('message from {}'.format(person)) return person
"""Catalyst is a release building tool used by Gentoo Linux""" from __future__ import print_function import codecs as _codecs from distutils.core import setup as _setup, Command as _Command from email.utils import parseaddr as _parseaddr import os as _os from catalyst import __version__, __maintainer__ from catalyst.version import set_release_version as _set_release_version from catalyst.version import get_version as _get_version _this_dir = _os.path.dirname(__file__) _package_name = 'catalyst' _maintainer_name, _maintainer_email = _parseaddr(__maintainer__) def _posix_path(path): """Convert a native path to a POSIX path Distutils wants all paths to be written in the Unix convention (i.e. slash-separated) [1], so that's what we'll do here. [1]: https://docs.python.org/2/distutils/setupscript.html """ if _os.path.sep != '/': return path.replace(_os.path.sep, '/') return path
def _get_message_person(course, message, trust_admin_from=True): """Get the `Person` that sent the message. We use 'Return-Path' (envelope from) instead of the message's From header, because it's more consistent and harder to fake. However, there may be times when you *want* to send a message in somebody elses name. For example, if a student submitted an assignment from an unexpected address, you might add that address to their entry in your course config, and then bounce the message back into pygrader. In this case, the From header will still be the student, but the 'Return-Path' will be you. With `trust_admin_from` (on by default), messages who's 'Return-Path' matches a professor or TA will have their 'From' line used to find the final person responsible for the message. >>> from pygrader.model.course import Course >>> from pygrader.model.person import Person >>> from pgp_mime import encodedMIMEText >>> course = Course(people=[ ... Person( ... name='Gandalf', emails=['*****@*****.**'], groups=['professors']), ... Person(name='Bilbo', emails=['*****@*****.**']), ... ]) >>> message = encodedMIMEText('testing') >>> message['Return-Path'] = '<*****@*****.**>' >>> message['From'] = 'Bill <*****@*****.**>' >>> message['Message-ID'] = '<*****@*****.**>' >>> person = _get_message_person(course=course, message=message) >>> print(person) <Person Bilbo> >>> person = _get_message_person( ... course=course, message=message, trust_admin_from=False) >>> print(person) <Person Gandalf> """ sender = message['return-path'] # RFC 822 if sender is None: raise NoReturnPath(message) sender = sender[1:-1] # strip wrapping '<' and '>' people = list(course.find_people(email=sender)) if len(people) == 0: raise UnregisteredAddress(message=message, address=sender) if len(people) > 1: raise AmbiguousAddress(message=message, address=sender, people=people) person = people[0] if trust_admin_from and person.is_admin(): mid = message['message-id'] from_headers = message.get_all('from') if len(from_headers) == 0: _LOG.debug("no 'From' headers in {}".format(mid)) elif len(from_headers) > 1: _LOG.debug("multiple 'From' headers in {}".format(mid)) else: name, address = _parseaddr(from_headers[0]) people = list(course.find_people(email=address)) if len(people) == 0: _LOG.debug("'From' address {} is unregistered".format(address)) if len(people) > 1: _LOG.debug("'From' address {} is ambiguous".format(address)) _LOG.debug('message from {} treated as being from {}'.format( person, people[0])) person = people[0] _LOG.debug('message from {}'.format(person)) return person
def validate_email_address(email_id: str) -> str: if "@" in _parseaddr(email_id)[1]: return email_id raise AppException("Invalid Email")