def form_valid(self, form): # save the result data = DynamicFormData.objects.create( dynamicform = self.dynamicform, raw_post_data = self.request.raw_post_data, headers = '\n'.join( '%s: %s' % (h, self.request.META[h]) for h in HTTP_HEADERS if h in self.request.META ) ) # create confirmation e-mail if self.dynamicform.send_confirmation: recipients_template = Template(self.dynamicform.email_recipients) subject_template = Template(self.dynamicform.email_subject) content_template = Template(self.dynamicform.email_content) context = Context(form.cleaned_data) recipients = recipients_template.render(context) subject = subject_template.render(context) content = content_template.render(context) msg = EmailMultiAlternatives( force_unicode(subject), html2text(content), settings.DEFAULT_FROM_EMAIL, [address for name, address in rfc822.AddressList(recipients).addresslist], ) msg.attach_alternative(content, "text/html") msg.send() # create e-mail for dynamicform manager if self.dynamicform.notification_emails: recipients = self.dynamicform.notification_emails.split(u',') subject = _(u'Someone filled in your online form "%s"') % self.dynamicform.name context = RequestContext( self.request, { 'form': form, 'dynamicform': self.dynamicform, 'dynamicformdata': data, 'site': Site.objects.get_current(), }, ) content = render_to_string(self.dynamicform.email_template, context_instance=context) msg = EmailMultiAlternatives( force_unicode(subject), html2text(content), settings.SERVER_EMAIL, [address for name, address in rfc822.AddressList(recipients).addresslist], ) msg.attach_alternative(content, "text/html") msg.send() return super(ProcessDynamicFormView, self).form_valid(form)
def difference_of_address_lists(addresses, to_remove): address_set = dict([(address, True) for (_, address) in rfc822.AddressList(addresses)]) for name, address in rfc822.AddressList(to_remove): if address in address_set: del address_set[address] address_list = [ rfc822.dump_address_pair(('', address)) for address in address_set.iterkeys() ] address_list.sort() return ','.join(address_list)
def _mungeHeaders(messageText, mto=None, mfrom=None, subject=None): """Sets missing message headers, and deletes Bcc. returns fixed message, fixed mto and fixed mfrom""" mfile = StringIO(messageText.lstrip()) mo = rfc822.Message(mfile) # Parameters given will *always* override headers in the messageText. # This is so that you can't override or add to subscribers by adding them to # the message text. if subject: mo['Subject'] = subject elif not mo.getheader('Subject'): mo['Subject'] = '[No Subject]' if mto: if isinstance(mto, basestring): mto = [ rfc822.dump_address_pair(addr) for addr in rfc822.AddressList(mto) ] if not mo.getheader('To'): mo['To'] = ','.join(mto) else: mto = [] for header in ('To', 'Cc', 'Bcc'): v = mo.getheader(header) if v: mto += [ rfc822.dump_address_pair(addr) for addr in rfc822.AddressList(v) ] if not mto: raise MailHostError, "No message recipients designated" if mfrom: mo['From'] = mfrom else: if mo.getheader('From') is None: raise MailHostError, "Message missing SMTP Header 'From'" mfrom = mo['From'] if mo.getheader('Bcc'): mo.__delitem__('Bcc') if not mo.getheader('Date'): mo['Date'] = DateTime().rfc822() mo.rewindbody() finalmessage = mo finalmessage = mo.__str__() + '\n' + mfile.read() mfile.close() return finalmessage, mto, mfrom
def generateBounce(message, failedFrom, failedTo, transcript=''): if not transcript: transcript = '''\ I'm sorry, the following address has permanent errors: %(failedTo)s. I've given up, and I will not retry the message again. ''' % vars() boundary = "%s_%s_%s" % (time.time(), os.getpid(), 'XXXXX') failedAddress = rfc822.AddressList(failedTo)[0][1] failedDomain = failedAddress.split('@', 1)[1] messageID = smtp.messageid(uniq='bounce') ctime = time.ctime(time.time()) fp = StringIO.StringIO() fp.write(BOUNCE_FORMAT % vars()) orig = message.tell() message.seek(2, 0) sz = message.tell() message.seek(0, orig) if sz > 10000: while 1: line = message.readline() if len(line) <= 1: break fp.write(line) else: fp.write(message.read()) return '', failedFrom, fp.getvalue()
def parse_mimepart_address_header(mimepart, header_name): header_list_string = ', '.join(mimepart.headers.getall(header_name)) addresslist = rfc822.AddressList(header_list_string).addresslist if len(addresslist) > 1: # Deduplicate entries return list(set(addresslist)) return addresslist
def on_send(self, obj): try: smtp = smtplib.SMTP(sqmail.preferences.get_outgoingserver(), \ sqmail.preferences.get_outgoingport()) smtp.set_debuglevel(sqmail.preferences.get_smtpdebuglevel()) fromaddr = self.widget.fromfield.get_text() # Construct the To: list. First, work out what the user asked # for... toaddr = [] for i in rfc822.AddressList( self.widget.tofield.get_text()).addresslist: toaddr.append(i[1]) # ...and expand aliases and unqualified addresses. toaddr = self.expand_addrlist(toaddr) # Construct and send the message itself. msgstring = self.makemessage( tofield=sqmail.gui.utils.render_addrlist(toaddr)) smtp.sendmail(fromaddr, toaddr, msgstring) smtp.quit() # If we got this far, the message went out successfully. # Incorporate the message into the database (for the outbox). msg = sqmail.message.Message() msg.loadfromstring(msgstring) msg.date = time.time() msg.readstatus = "Sent" msg.savealltodatabase() # We can destroy the send window. self.widget.composewin.destroy() except RuntimeError, e: sqmail.gui.utils.errorbox(str(e))
def _GetOwnerID(user_svc, cnxn, owner_email): if owner_email: owner_email = owner_email.strip() if not owner_email: return None emails = [addr for _, addr in rfc822.AddressList(owner_email)] return user_svc.LookupExistingUserIDs(cnxn, emails).get(owner_email)
def sender(self): fromHeader = self['from'] or '"Nobody" <nobody@nowhere>' hdrs = rfc822.AddressList(fromHeader).addresslist for dispname, addr in hdrs: dispname = dispname.strip().strip('"') addr = addr.strip() if dispname == '': dispname = addr return dispname
def generateBounce(message, failedFrom, failedTo, transcript=''): """ Generate a bounce message for an undeliverable email message. @type message: L{bytes} @param message: The undeliverable message. @type failedFrom: L{bytes} @param failedFrom: The originator of the undeliverable message. @type failedTo: L{bytes} @param failedTo: The destination of the undeliverable message. @type transcript: L{bytes} @param transcript: An error message to include in the bounce message. @rtype: 3-L{tuple} of (E{1}) L{bytes}, (E{2}) L{bytes}, (E{3}) L{bytes} @return: The originator, the destination and the contents of the bounce message. The destination of the bounce message is the originator of the undeliverable message. """ if not transcript: transcript = '''\ I'm sorry, the following address has permanent errors: %(failedTo)s. I've given up, and I will not retry the message again. ''' % { 'failedTo': failedTo } failedAddress = rfc822.AddressList(failedTo)[0][1] data = { 'boundary': "%s_%s_%s" % (time.time(), os.getpid(), 'XXXXX'), 'ctime': time.ctime(time.time()), 'failedAddress': failedAddress, 'failedDomain': failedAddress.split('@', 1)[1], 'failedFrom': failedFrom, 'failedTo': failedTo, 'messageID': smtp.messageid(uniq='bounce'), 'message': message, 'transcript': transcript, } fp = StringIO.StringIO() fp.write(BOUNCE_FORMAT % data) orig = message.tell() message.seek(2, 0) sz = message.tell() message.seek(0, orig) if sz > 10000: while 1: line = message.readline() if len(line) <= 1: break fp.write(line) else: fp.write(message.read()) return '', failedFrom, fp.getvalue()
def parseEmailAddresses(addresses, mimeEncoded=True): """Parse a list of comma separated addresses and might be found in an email header. @param mimeEncoded: as parameter by same name to EmailAddress.__init__ @return a list of EmailAddress instances. """ return [ EmailAddress(address, mimeEncoded=mimeEncoded) for address in rfc822.AddressList(addresses) ]
def _GetCCIDs(user_svc, cnxn, cc_emails): if cc_emails: cc_emails = cc_emails.strip() if not cc_emails: return [] emails = [addr for _, addr in rfc822.AddressList(cc_emails)] return [ userID for _, userID in user_svc.LookupExistingUserIDs( cnxn, emails).iteritems() if userID is not None ]
def parseBuddies(self): try: self.buddyList = rfc822.AddressList(self.buddiesfile.open().read()) except IOError: return self.clearContactMenu() for dispn, addr in self.buddyList: if addr not in self.loadedBuddies: BuddyItem(self, dispn, addr) self.buildContactMenu()
def parse_address_hval(hval): """ Given a address collection header value, parse out the name/email pairs into a list of (name, email) :param string hval: Email address strings :return set[string, string] """ addresses = set() for phrase, addrspec in rfc822.AddressList(hval).addresslist: addresses.add((decode(phrase), decode(addrspec))) return sorted(elem for elem in addresses)
def rfc2047_encode_address(addr, charset, mua=None): newlist = [] addresses = rfc822.AddressList(addr).addresslist for (realname, address) in addresses: if realname: newlist.append( email.Utils.formataddr( (str(rfc2047_encode_header(realname, charset, mua)), address))) else: newlist.append(address) return ', '.join(newlist)
def send(self, **kw): msg, values, headers = self._process(kw) for header, value in headers: msg[header] = value to_addrs = () for key in ('mto', 'mcc', 'mbcc'): v = values.get(key) if v: if isinstance(v, basestring): v = [rfc822.dump_address_pair(addr) for addr \ in rfc822.AddressList(v)] to_addrs += tuple(v) self._send(values['mfrom'], to_addrs, msg)
def _validateAndNormalizeEmail(self, address): """ Validates and normalizes an email address.""" address = address.strip() if not address: raise ValidationError('No email address given') try: a = rfc822.AddressList(address) except: raise ValidationError('Email address was not compliant with ' 'rfc822') if len(a.addresslist) > 1: raise ValidationError('More than one email address was given') try: address = a.addresslist[0][1] except: raise ValidationError('Unexpected validation error') if not address: raise ValidationError('No email address given') return address
def clean_email(self): """ Validate that the email is not already used by a registered user and has not already been sent an invite. """ addresses = rfc822.AddressList(self.cleaned_data['email']) for (name, email) in addresses.addresslist: user = CustomUser.objects.all()\ .filter(email=email.lower()) if user: raise forms.ValidationError(strings.INVITE_ERROR_REGISTERED % email) invite = Invitation.objects.all()\ .filter(email=email.lower()) if invite: raise forms.ValidationError(strings.INVITE_ERROR_INVITED % email) return addresses.addresslist
def parse_mimepart_address_header(mimepart, header_name): # Header parsing is complicated by the fact that: # (1) You can have multiple occurrences of the same header; # (2) Phrases or comments can be RFC2047-style encoded words; # (3) Everything is terrible. # Here, for each occurrence of the header in question, we first parse # it into a list of (phrase, addrspec) tuples and then use flanker to # decode any encoded words. # You want to do it in that order, because otherwise if you get a header # like # From: =?utf-8?Q?FooCorp=2C=20Inc.=? <*****@*****.**> # you can end up parsing 'FooCorp, Inc. <*****@*****.**> (note lack of # quoting) into two separate addresses. # Consult RFC822 Section 6.1 and RFC2047 section 5 for details. addresses = set() for section in mimepart.headers._v.getall(normalize(header_name)): for phrase, addrspec in rfc822.AddressList(section).addresslist: addresses.add((decode(phrase), decode(addrspec))) # Return a list of lists because it makes it easier to compare an address # field to one which has been fetched from the db. return sorted(list(elem) for elem in addresses)
def union_of_address_lists(*email_lists): """ Takes comma separated lists of RFC822 email address and returns a comma separated list with the union of the addresses. *email_lists : str -- as entered in an email address, e.g. '[email protected], Bob <*****@*****.**>' returns : str -- a comma separated list of addresses. """ address_set = {} for email_list in email_lists: for name, address in rfc822.AddressList(email_list): address_set[address] = True address_list = [ rfc822.dump_address_pair(('', address)) for address in address_set.iterkeys() ] address_list.sort() return ','.join(address_list)
def parseOptions(argv): o = Options() o.to = [e for e in argv if not e.startswith('-')] o.sender = getlogin() # Just be very stupid # Skip -bm -- it is the default # -bp lists queue information. Screw that. if '-bp' in argv: raise _unsupportedOption # -bs makes sendmail use stdin/stdout as its transport. Screw that. if '-bs' in argv: raise _unsupportedOption # -F sets who the mail is from, but is overridable by the From header if '-F' in argv: o.sender = argv[argv.index('-F') + 1] o.to.remove(o.sender) # -i and -oi makes us ignore lone "." if ('-i' in argv) or ('-oi' in argv): raise _unsupportedOption # -odb is background delivery if '-odb' in argv: o.background = True else: o.background = False # -odf is foreground delivery if '-odf' in argv: o.background = False else: o.background = True # -oem and -em cause errors to be mailed back to the sender. # It is also the default. # -oep and -ep cause errors to be printed to stderr if ('-oep' in argv) or ('-ep' in argv): o.printErrors = True else: o.printErrors = False # -om causes a copy of the message to be sent to the sender if the sender # appears in an alias expansion. We do not support aliases. if '-om' in argv: raise _unsupportedOption # -t causes us to pick the recipients of the message from the To, Cc, and Bcc # headers, and to remove the Bcc header if present. if '-t' in argv: o.recipientsFromHeaders = True o.excludeAddresses = o.to o.to = [] else: o.recipientsFromHeaders = False o.exludeAddresses = [] requiredHeaders = { 'from': [], 'to': [], 'cc': [], 'bcc': [], 'date': [], } headers = [] buffer = StringIO.StringIO() while 1: write = 1 line = sys.stdin.readline() if not line.strip(): break hdrs = line.split(': ', 1) hdr = hdrs[0].lower() if o.recipientsFromHeaders and hdr in ('to', 'cc', 'bcc'): o.to.extend( [a[1] for a in rfc822.AddressList(hdrs[1]).addresslist]) if hdr == 'bcc': write = 0 elif hdr == 'from': o.sender = rfc822.parseaddr(hdrs[1])[1] if hdr in requiredHeaders: requiredHeaders[hdr].append(hdrs[1]) if write: buffer.write(line) if not requiredHeaders['from']: buffer.write('From: %s\r\n' % (o.sender, )) if not requiredHeaders['to']: if not o.to: raise SystemExit("No recipients specified.") buffer.write('To: %s\r\n' % (', '.join(o.to), )) if not requiredHeaders['date']: buffer.write('Date: %s\r\n' % (smtp.rfc822date(), )) buffer.write(line) if o.recipientsFromHeaders: for a in o.excludeAddresses: try: o.to.remove(a) except: pass buffer.seek(0, 0) o.body = StringIO.StringIO(buffer.getvalue() + sys.stdin.read()) return o
def mainloop(): while 1: # Are there any files in the spool directory? to_be_sent = [] all_files = [] for spool in MAILDROP_SPOOLS: all_files.extend([os.path.join(spool, x) for x in os.listdir(spool)]) # Remove lock files clean_files = [x for x in all_files if not x.endswith('.lck')] # Remove files that were locked by the previously removed lock files clean_files = [x for x in clean_files if not '%s.lck' % x in all_files] # Remove directories to_be_sent = [x for x in clean_files if not os.path.isdir(x)] if len(to_be_sent) > 0: # Open the log file time_stamp = time.strftime('%Y/%m/%d %H:%M:%S') log_file = open(MAILDROP_LOG_FILE, 'a') msg = '\n### Started at %s...' % time_stamp log_file.write(msg) if DEBUG: print msg while len(to_be_sent) > 0: if (MAILDROP_BATCH == 0) or (MAILDROP_BATCH > len(to_be_sent)): batch = len(to_be_sent) else: batch = MAILDROP_BATCH # Send mail try: smtp_server = smtplib.SMTP(SMTP_HOST, SMTP_PORT) #smtp_server.set_debuglevel(1) smtp_server.ehlo() except smtplib.SMTPConnectError: # SMTP server did not respond. Log it and stop processing. time_stamp = time.strftime('%Y/%m/%d %H:%M:%S') err_msg = '!!!!! Connection error at %s' % time_stamp finish_msg = '### Finished at %s' % time_stamp log_file.write(err_msg) if DEBUG: print err_msg log_file.write(finish_msg) if DEBUG: print finish_msg log_file.close() break if MAILDROP_TLS > 0: if (MAILDROP_TLS > 1 and not smtp_server.has_extn('starttls')): # Problem: TLS is required but the server does not # offer it We stop processing here. time_stamp = time.strftime('%Y/%m/%d %H:%M:%S') err_msg = '!!!!! TLS unavailable at %s' % time_stamp finish_msg = '### Finished at %s' % time_stamp log_file.write(err_msg) if DEBUG: print err_msg log_file.write(finish_msg) if DEBUG: print finish_msg log_file.close() break smtp_server.starttls() # We have to say Hello again after starting TLS smtp_server.ehlo() if MAILDROP_LOGIN != '' and MAILDROP_PASSWORD != '': # Login is required to send mail if not smtp_server.has_extn('auth'): # The server does not offer authentication but we want it # We stop processing here. time_stamp = time.strftime('%Y/%m/%d %H:%M:%S') err_msg = '!!!!! Authentication unavailable at %s' % time_stamp finish_msg = '### Finished at %s' % time_stamp log_file.write(err_msg) if DEBUG: print err_msg log_file.write(finish_msg) if DEBUG: print finish_msg log_file.close() break try: smtp_server.login(MAILDROP_LOGIN, MAILDROP_PASSWORD) except smtplib.SMTPAuthenticationError: # Authentication with the given credentials fails. # We stop processing here. time_stamp = time.strftime('%Y/%m/%d %H:%M:%S') err_msg = '!!!!! Authentication failed at %s' % time_stamp finish_msg = '### Finished at %s' % time_stamp log_file.write(err_msg) if DEBUG: print err_msg log_file.write(finish_msg) if DEBUG: print finish_msg log_file.close() break for file_path in to_be_sent[0:batch]: mail_dict = read_mail(file_path) if not mail_dict: continue # Create mail and send it off h_from = mail_dict.get('From') h_to = mail_dict.get('To') h_to_list = [] for item in rfc822.AddressList(h_to): h_to_list.append(item[1]) h_body = mail_dict.get('body') if ADD_MESSAGEID: h_body = 'Message-Id: %s\n%s' % (make_msgid(), h_body) try: smtp_server.sendmail(h_from, h_to_list, h_body) stat = 'OK' os.remove(file_path) except smtplib.SMTPRecipientsRefused, e: stat = 'FATAL: ', str(e) for (addr, error) in e.recipients.items(): if str(error[0]) in FATAL_ERROR_CODES: os.remove(file_path) break except smtplib.SMTPException, e: stat = 'BAD: ', str(e) mail_msg = '\n%s\t %s' % (stat, h_to) log_file.write(mail_msg) if DEBUG: print mail_msg log_file.flush() if WAIT_INTERVAL: time.sleep(WAIT_INTERVAL) to_be_sent = to_be_sent[batch:] try: smtp_server.quit() except smtplib.SMTPServerDisconnected: pass time_stamp = time.strftime('%Y/%m/%d %H:%M:%S') finish_msg = '\n### Finished at %s\n' % time_stamp log_file.write(finish_msg) if DEBUG: print finish_msg log_file.close()
def _ExtractAddrs(header_value): """Given a message header value, return email address found there.""" friendly_addr_pairs = list(rfc822.AddressList(header_value)) return [addr for _friendly, addr in friendly_addr_pairs]
def get_email_addr(addr): addr = rfc822.AddressList(addr) return addr.addresslist[0]
MailRelay = pyca_section.get('MailRelay', 'localhost') caCertReqMailAdr = pyca_section.get('caCertReqMailAdr', '') caInternalCertTypes = pyca_section.get('caInternalCertTypes', []) caInternalDomains = pyca_section.get('caInternalDomains', '') if type(caInternalDomains) != type([]): caInternalDomains = [caInternalDomains] m = rfc822.Message(sys.stdin) if len(m["subject"]) > 80: LogWrite(logfile, 'Error', m, 'Subject too long.') sys.exit(0) if m.has_key('from'): from_addr = mime_decode_header(string.strip(m["from"])) from_name, from_mail = rfc822.AddressList(from_addr).addresslist[0] else: from_mail = '' subject = string.strip(m["subject"]) subjectstart = string.find(subject, 'cert-req-') try: prefix, ca_name, caChallengeId = string.split( subject[subjectstart:len(subject)], '.', 2) except ValueError: LogWrite(logfile, 'Error', m, 'Subject has wrong format.') sys.exit(0) if prefix == 'cert-req-SPKAC': request_filenamesuffix = 'spkac'
def set_title(request, rcfg, doc, feed, update_ts): """This function attaches the necessary RSS/Atom feed elements needed to provide title, author and contact information to the provided xmini document object using the provided feed object and update time. """ t = doc.createElement("title") ti = xmini.Text() ti.replaceWholeText(rcfg.get_attribute("feed", "name")) t.appendChild(ti) feed.appendChild(t) l = doc.createElement("link") l.setAttribute("href", cherrypy.url()) l.setAttribute("rel", "self") feed.appendChild(l) # Atom requires each feed to have a permanent, universally unique # identifier. i = doc.createElement("id") it = xmini.Text() it.replaceWholeText("urn:uuid:%s" % rcfg.get_attribute("feed", "id")) i.appendChild(it) feed.appendChild(i) # Indicate when the feed was last updated. u = doc.createElement("updated") ut = xmini.Text() ut.replaceWholeText(dt_to_rfc3339_str(update_ts)) u.appendChild(ut) feed.appendChild(u) # Add our icon. i = doc.createElement("icon") it = xmini.Text() it.replaceWholeText(rcfg.get_attribute("feed", "icon")) i.appendChild(it) feed.appendChild(i) # Add our logo. l = doc.createElement("logo") lt = xmini.Text() lt.replaceWholeText(rcfg.get_attribute("feed", "logo")) l.appendChild(lt) feed.appendChild(l) maintainer = rcfg.get_attribute("repository", "maintainer") # The author information isn't required, but can be useful. if maintainer: name, email = rfc822.AddressList(maintainer).addresslist[0] if email and not name: # If we got an email address, but no name, then # the name was likely parsed as a local address. In # that case, assume the whole string is the name. name = maintainer email = None a = doc.createElement("author") # First we have to add a name element. This is required if an # author element exists. n = doc.createElement("name") nt = xmini.Text() nt.replaceWholeText(name) n.appendChild(nt) a.appendChild(n) if email: # If we were able to extract an email address from the # maintainer information, add the optional email # element to provide a point of communication. e = doc.createElement("email") et = xmini.Text() et.replaceWholeText(email) e.appendChild(et) a.appendChild(e) # Done with the author. feed.appendChild(a)