def main(args): try: opts, args = getopt.getopt(args, "hd:S:H:f:", ["help", "database=", "spamfile=", "hamfile=", "feature="]) except getopt.GetoptError as msg: usage(msg) return 1 charset = locale.getdefaultlocale()[1] if not charset: charset = 'us-ascii' mapfile = spamfile = hamfile = None features = set() for opt, arg in opts: if opt in ("-h", "--help"): usage() return 0 elif opt in ("-d", "--database"): mapfile = arg elif opt in ("-H", "--hamfile"): hamfile = arg elif opt in ("-S", "--spamfile"): spamfile = arg elif opt in ("-f", "--feature"): features.add(str(arg, charset)) if hamfile is None and spamfile is None: usage("At least one of -S or -H are required") return 1 if mapfile is None: usage("'-d mapfile' is required") return 1 try: mapd = pickle_read(mapfile) except IOError: usage("Mapfile %s does not exist" % mapfile) return 1 if not features and not args: usage("Require at least one feature (-f) arg or one message file") return 1 if not features: for f in args: for msg in getmbox(f): evidence = msg.get("X-Spambayes-Evidence", "") evidence = re.sub(r"\s+", " ", evidence) l = [e.rsplit(": ", 1)[0] for e in evidence.split("; ")[2:]] for s in l: try: s = make_header(decode_header(s)).__unicode__() except: s = str(s, 'us-ascii', 'replace') features.add(s) if not features: usage("No X-Spambayes-Evidence headers found") return 1 if spamfile is not None: spamfile = file(spamfile, "w") if hamfile is not None: hamfile = file(hamfile, "w") extractmessages(features, mapd, hamfile, spamfile)
def mailread(src): """生メールから件名,本文,添付ファイル(画像)を取り出す """ # Messageオブジェクトを作る m = email.message_from_string(src) # ヘッダをデコード subj = decode_header(m["Subject"]) # ヘッダを表示 try: print unicode(make_header(subj)) except: pass print "-" * 70 # 全パートをスキャン for part in m.walk(): type = part.get_content_maintype() # maintypeを得る if type and type.find("image") != -1: # 画像の添付が見つかったら,ファイルに保存 filename = part.get_filename("notitle.img") f = open(filename, "wb") f.write(part.get_payload(decode=True)) f.close() if type and type.find("text") != -1: # テキストは表示 enc = part.get_charsets()[0] or "us-ascii" print part.get_payload().decode(enc, "ignore")
def sendmail(to, subject, message): #authorization data username = '******' password = '******' #message generating msg = MIMEMultipart() #header hdr = make_header([(subject, icharset)]) #params msg['From'] = username msg['To'] = to msg['Date'] = formatdate(localtime=True) msg['Subject'] = hdr #message body: encoding->html->cp866 msg.attach(MIMEText(message, 'html', icharset)) #connection srv = smtplib.SMTP(server, port) srv.ehlo() #starting ssl srv.starttls() srv.ehlo() #authorization srv.login(username, password) #sending srv.sendmail(username, to, msg.as_string()) #closing connection srv.close()
def __decode_header(header): """Decode a qp-encoded e-mail header as per rfc2047""" try: words_enc = decode_header(header) hobj = make_header(words_enc) except Exception, ex: raise CmdException, "header decoding error: %s" % str(ex)
def update(self): super(SendNewsletter, self).update() if 'form.send' in self.request: subs = ISubscribersManagement(self.context.__parent__) emails = [] for principal in subs.getSubscribers(): mail = IMailAddress(principal, None) if mail is not None: email = mail.address if email: emails.append( formataddr((principal.title or principal.id, email))) if emails: message = self.generateMessage() message['Subject'] = make_header(((self.context.title, 'utf-8'),)) mailer = getUtility(IMailer) from_address = str(formataddr( (mailer.email_from_name, mailer.email_from_address))) message['From'] = from_address mailer.send(from_address, emails, message.as_string()) IStatusMessage(self.request).add(_('Newsletter has been sent.'))
def mailread(src): """生メールから件名、本文、添付ファイル(画像)を取り出す """ # Messageオブジェクトを作る m = email.message_from_string(src) # ヘッダをデコード subj = decode_header(m["Subject"]) # ヘッダを表示 try: print unicode(make_header(subj)) except: pass; print "-" * 70 # 全パートをスキャン for part in m.walk(): type = part.get_content_maintype() # maintypeを得る if type and type.find("image") != -1: # 画像の添付が見つかったら、ファイルに保存 filename = part.get_filename("notitle.img") f = open(filename, "wb") f.write(part.get_payload(decode = True)) f.close() elif type and type.find("text") != -1: # テキストは表示 enc ~ part.get_charsets()[0] or "us-ascii" print part.get_payload().decode(enc, "ignore")
def sendmail(to, subject, message): # данные авторизации username = '******' password = '******' ### генерация передаваемого содобщения msg = MIMEMultipart() # заголовок hdr = make_header([(subject, icharset)]) # параметры письма (отправитель, получатель, дата, тема письма msg['From'] = username msg['To'] = to msg['Date'] = formatdate(localtime=True) msg['Subject'] = hdr # добавление к содержимому текста сообщения msg.attach(MIMEText(message, _charset=icharset)) ### передача сообщения # установка соединения srv = smtplib.SMTP(server, port) srv.ehlo() # запуск шифрования (SSL соединение) srv.starttls() srv.ehlo() # авторизация srv.login(username, password) # передача сообщения srv.sendmail(username, to, msg.as_string()) # завершение соединения srv.close()
def send_mail(to, subject, text, attach): ### if settings.DEBUG: logger.debug(u"\n{}\n{}\n{}\n".format(to, subject, text)) return ### try: msg = MIMEMultipart('related') organization = settings.MAIL_SENDER_ORGANIZATION mailer = settings.MAIL_SENDER_MAILER msg['Message-ID'] = msgid() msg['Organization'] = make_header([(organization, 'UTF-8')]) msg['X-Mailer'] = make_header([(mailer, 'UTF-8')]) msg['From'] = make_header([(mailer, 'UTF-8'), ('<' + settings.MAIL_SENDER_SENDER + '>', 'us-ascii')]) msg['To'] = make_header([(to, 'us-ascii')]) msg['Subject'] = make_header([(subject, 'UTF-8')]) msg.preamble = "This is a multi-part message in MIME format." msg.epilogue = "End of message" # alternative part msgAlternative = MIMEMultipart('alternative') msg.attach(msgAlternative) msgText = MIMEText(text, '', 'utf-8') msgAlternative.attach(msgText) # html part to_attach = MIMEText(text.encode('utf-8'), 'html', 'utf-8') msgAlternative.attach(to_attach) if attach: part = MIMEBase('application', 'octet-stream') part.set_payload(open(attach, 'rb').read()) encode_base64(part) part.add_header('Content-Disposition', 'attachment; filename="%s"' % os.path.basename(attach)) msg.attach(part) mailServer = smtplib.SMTP(settings.MAIL_SENDER_SERVER, settings.MAIL_SENDER_PORT) mailServer.ehlo() mailServer.starttls() mailServer.ehlo() mailServer.login(settings.MAIL_SENDER_USER, settings.MAIL_SENDER_PASSWORD) mailServer.sendmail(settings.MAIL_SENDER_SENDER, to, msg.as_string()) # Should be mailServer.quit(), but that crashes... mailServer.close() except Exception as e: logger.error(u'\n\nMessage to "{}" with subject "{}" was not sended\nException message: "{}"\n'.format(to, subject, e.message)) return
def setHeaders(self, message): charset = str(self.context.charset) extra = list(self.context.getHeaders()) for key, val, encode in self._headers.values() + extra: if encode: message[key] = make_header(((val, charset),)) else: message[key] = val
def decode_email(self, file): # Prepare result theMail = { 'attachment_list': [], 'body': '', # Place all the email header in the headers dictionary in theMail 'headers': {} } # Get Message msg = email.message_from_string(file) # Back up original file theMail['__original__'] = file # Recode headers to UTF-8 if needed for key, value in msg.items(): decoded_value_list = decode_header(value) unicode_value = make_header(decoded_value_list) new_value = unicode_value.__unicode__().encode('utf-8') theMail['headers'][key.lower()] = new_value # Filter mail addresses for header in ('resent-to', 'resent-from', 'resent-cc', 'resent-sender', 'to', 'from', 'cc', 'sender', 'reply-to'): header_field = theMail['headers'].get(header) if header_field: theMail['headers'][header] = parseaddr(header_field)[1] # Get attachments body_found = 0 for part in msg.walk(): content_type = part.get_content_type() file_name = part.get_filename() # multipart/* are just containers # XXX Check if data is None ? if content_type.startswith('multipart'): continue # message/rfc822 contains attached email message # next 'part' will be the message itself # so we ignore this one to avoid doubling elif content_type == 'message/rfc822': continue elif content_type in ("text/plain", "text/html"): charset = part.get_content_charset() payload = part.get_payload(decode=True) #LOG('CMFMailIn -> ',0,'charset: %s, payload: %s' % (charset,payload)) if charset: payload = unicode(payload, charset).encode('utf-8') if body_found: # Keep the content type theMail['attachment_list'].append((file_name, content_type, payload)) else: theMail['body'] = payload body_found = 1 else: payload = part.get_payload(decode=True) # Keep the content type theMail['attachment_list'].append((file_name, content_type, payload)) return theMail
def header(text): if not text: text = '' if not isinstance(text, text_type): text = text.decode('latin1') try: text = html2text(text).strip() except UnicodeError: pass return make_header([(text, 'utf-8')]).encode()
def decode_charset(self, field): # TK: This function was rewritten for unifying to Unicode. # Convert 'field' into Unicode one line string. try: pairs = decode_header(field) ustr = make_header(pairs).__unicode__() except (LookupError, UnicodeError, ValueError, HeaderParseError): # assume list's language cset = Utils.GetCharSet(self._mlist.preferred_language) if cset == 'us-ascii': cset = 'iso-8859-1' # assume this for English list ustr = unicode(field, cset, 'replace') return u''.join(ustr.splitlines())
def __init__(self, mlist, msg, msgdata): self.mlist = mlist self.msg = msg self.msgdata = msgdata # Only set returnaddr if the response is to go to someone other than # the address specified in the From: header (e.g. for the password # command). self.returnaddr = None self.commands = [] self.results = [] self.ignored = [] self.lineno = 0 self.subjcmdretried = 0 self.respond = True # Extract the subject header and do RFC 2047 decoding. Note that # Python 2.1's unicode() builtin doesn't call obj.__unicode__(). subj = msg.get('subject', '') try: subj = make_header(decode_header(subj)).__unicode__() # TK: Currently we don't allow 8bit or multibyte in mail command. # MAS: However, an l10n 'Re:' may contain non-ascii so ignore it. subj = subj.encode('us-ascii', 'ignore') # Always process the Subject: header first self.commands.append(subj) except (HeaderParseError, UnicodeError, LookupError): # We couldn't parse it so ignore the Subject header pass # Find the first text/plain part part = None for part in typed_subpart_iterator(msg, 'text', 'plain'): break if part is None or part is not msg: # Either there was no text/plain part or we ignored some # non-text/plain parts. self.results.append(_('Ignoring non-text/plain MIME parts')) if part is None: # E.g the outer Content-Type: was text/html return # convert message into unicode because 'utf-8' message increasing mcset = part.get_content_charset('us-ascii') body = unicode(part.get_payload(decode=True), mcset, 'replace') # text/plain parts better have string payloads assert isinstance(body, StringType) or isinstance(body, UnicodeType) lines = body.splitlines() # Use no more lines than specified self.commands.extend(lines[:mm_cfg.DEFAULT_MAIL_COMMANDS_MAX_LINES]) self.ignored.extend(lines[mm_cfg.DEFAULT_MAIL_COMMANDS_MAX_LINES:])
def makeEmail(mtext, context, headers={}): """ Make email message. """ ptool = getUtility(IPropertiesTool) email_charset = ptool.getProperty('email_charset', None) or 'utf-8' try: msg = MIMEText(mtext.encode('ascii'), 'plain') except UnicodeEncodeError: msg = MIMEText(mtext.encode(email_charset), 'plain', email_charset) for k, val in headers.items(): if isinstance(val, str): val = decode(val, context) if isinstance(val, i18n.Message): val = translate(val, context) header = make_header([ (w, email_charset) for w in val.split(' ') ]) msg[k] = str(header) return msg.as_string()
def makeEmail(mtext, context, headers={}): """ Make email message. """ ptool = getUtility(IPropertiesTool) email_charset = ptool.getProperty('email_charset', None) or 'utf-8' try: msg = MIMEText(mtext.encode(), 'plain') except UnicodeEncodeError: msg = MIMEText(mtext.encode(email_charset), 'plain', email_charset) for k, val in headers.items(): if isinstance(val, str): val = decode(val, context) if isinstance(val, i18n.Message): val = translate(val, context) header = make_header([(w, email_charset) for w in val.split(' ')]) msg[k] = str(header) return msg.as_string()
def __init__(self, mlist, msg, msgdata): self.mlist = mlist self.msg = msg self.msgdata = msgdata # Only set returnaddr if the response is to go to someone other than # the address specified in the From: header (e.g. for the password # command). self.returnaddr = None self.commands = [] self.results = [] self.ignored = [] self.lineno = 0 self.subjcmdretried = 0 self.respond = True # Extract the subject header and do RFC 2047 decoding. Note that # Python 2.1's unicode() builtin doesn't call obj.__unicode__(). subj = msg.get('subject', '') try: subj = make_header(decode_header(subj)).__unicode__() # TK: Currently we don't allow 8bit or multibyte in mail command. # MAS: However, an l10n 'Re:' may contain non-ascii so ignore it. subj = subj.encode('us-ascii', 'ignore') # Always process the Subject: header first self.commands.append(subj) except (HeaderParseError, UnicodeError, LookupError): # We couldn't parse it so ignore the Subject header pass # Find the first text/plain part part = None for part in typed_subpart_iterator(msg, 'text', 'plain'): break if part is None or part is not msg: # Either there was no text/plain part or we ignored some # non-text/plain parts. self.results.append(_('Ignoring non-text/plain MIME parts')) if part is None: # E.g the outer Content-Type: was text/html return body = part.get_payload(decode=True) # text/plain parts better have string payloads assert isinstance(body, StringType) or isinstance(body, UnicodeType) lines = body.splitlines() # Use no more lines than specified self.commands.extend(lines[:mm_cfg.DEFAULT_MAIL_COMMANDS_MAX_LINES]) self.ignored.extend(lines[mm_cfg.DEFAULT_MAIL_COMMANDS_MAX_LINES:])
def handleSendTesting(self, action): data, errors = self.extractData() if errors: IStatusMessage(self.request).add( (self.formErrorsMessage,) + errors, 'formError') else: message = self.generateMessage() message['Subject'] = make_header( ((u'Test message: %s'%self.context.title, 'utf-8'),)) mailer = getUtility(IMailer) from_address = formataddr( (mailer.email_from_name, mailer.email_from_address)) mailer.send(from_address, (data['email'],), message.as_string()) IStatusMessage(self.request).add( _('Test mail for newsletter has been sent.'))
def __init__(self, message): """Create a new user-to-user email entry. :param message: the message being sent :type message: `email.message.Message` """ super(UserToUserEmail, self).__init__() person_set = getUtility(IPersonSet) # Find the person who is sending this message. realname, address = parseaddr(message['from']) assert address, 'Message has no From: field' sender = person_set.getByEmail(address) assert sender is not None, 'No person for sender email: %s' % address # Find the person who is the recipient. realname, address = parseaddr(message['to']) assert address, 'Message has no To: field' recipient = person_set.getByEmail(address) assert recipient is not None, ('No person for recipient email: %s' % address) # Convert the date string into a UTC datetime. date = message['date'] assert date is not None, 'Message has no Date: field' self.date_sent = utcdatetime_from_field(date) # Find the subject and message-id. message_id = message['message-id'] assert message_id is not None, 'Message has no Message-ID: field' subject = message['subject'] assert subject is not None, 'Message has no Subject: field' # Initialize. self.sender = sender self.recipient = recipient self.message_id = unicode(message_id, 'ascii') self.subject = unicode(make_header(decode_header(subject))) # Add the object to the store of the sender. Our StormMigrationGuide # recommends against this saying "Note that the constructor should not # usually add the object to a store -- leave that for a FooSet.new() # method, or let it be inferred by a relation." # # On the other hand, we really don't need a UserToUserEmailSet for any # other purpose. There isn't any other relationship that can be # inferred, so in this case I think it makes fine sense for the # constructor to add self to the store. Also, this closely mimics # what the SQLObject compatibility layer does. Store.of(sender).add(self)
def __init__(self, message): """Create a new user-to-user email entry. :param message: the message being sent :type message: `email.message.Message` """ super(UserToUserEmail, self).__init__() person_set = getUtility(IPersonSet) # Find the person who is sending this message. realname, address = parseaddr(message['from']) assert address, 'Message has no From: field' sender = person_set.getByEmail(address) assert sender is not None, 'No person for sender email: %s' % address # Find the person who is the recipient. realname, address = parseaddr(message['to']) assert address, 'Message has no To: field' recipient = person_set.getByEmail(address) assert recipient is not None, ( 'No person for recipient email: %s' % address) # Convert the date string into a UTC datetime. date = message['date'] assert date is not None, 'Message has no Date: field' self.date_sent = utcdatetime_from_field(date) # Find the subject and message-id. message_id = message['message-id'] assert message_id is not None, 'Message has no Message-ID: field' subject = message['subject'] assert subject is not None, 'Message has no Subject: field' # Initialize. self.sender = sender self.recipient = recipient self.message_id = unicode(message_id, 'ascii') self.subject = unicode(make_header(decode_header(subject))) # Add the object to the store of the sender. Our StormMigrationGuide # recommends against this saying "Note that the constructor should not # usually add the object to a store -- leave that for a FooSet.new() # method, or let it be inferred by a relation." # # On the other hand, we really don't need a UserToUserEmailSet for any # other purpose. There isn't any other relationship that can be # inferred, so in this case I think it makes fine sense for the # constructor to add self to the store. Also, this closely mimics # what the SQLObject compatibility layer does. Store.of(sender).add(self)
def __call__(self, multipart_format='mixed', *args, **kw): context = self.context message = self.message(multipart_format, *args, **kw) message['Date'] = formatdate() message['Message-ID'] = context.messageId if not message.has_key('X-Mailer'): message['X-mailer'] = 'zojax.mailer' # update externals headers charset = str(context.charset) for name, adapter in getAdapters( (context, context.context), IMailHeaders): for name, value, encode in adapter.headers: if encode: message[name] = make_header(((value, charset),)) else: message[name] = value return message.as_string()
def ch_oneline(headerstr): # Decode header string in one line and convert into single charset # copied and modified from ToDigest.py and Utils.py # return (string, cset) tuple as check for failure try: d = decode_header(headerstr) # at this point, we should rstrip() every string because some # MUA deliberately add trailing spaces when composing return # message. d = [(s.rstrip(), c) for (s,c) in d] cset = 'us-ascii' for x in d: # search for no-None charset if x[1]: cset = x[1] break h = make_header(d) ustr = h.__unicode__() oneline = u''.join(ustr.splitlines()) return oneline.encode(cset, 'replace'), cset except (LookupError, UnicodeError, ValueError, HeaderParseError): # possibly charset problem. return with undecoded string in one line. return ''.join(headerstr.splitlines()), 'us-ascii'
def ch_oneline(headerstr): # Decode header string in one line and convert into single charset # copied and modified from ToDigest.py and Utils.py # return (string, cset) tuple as check for failure try: d = decode_header(headerstr) # at this point, we should rstrip() every string because some # MUA deliberately add trailing spaces when composing return # message. d = [(s.rstrip(), c) for (s, c) in d] cset = 'us-ascii' for x in d: # search for no-None charset if x[1]: cset = x[1] break h = make_header(d) ustr = h.__unicode__() oneline = u''.join(ustr.splitlines()) return oneline.encode(cset, 'replace'), cset except (LookupError, UnicodeError, ValueError, HeaderParseError): # possibly charset problem. return with undecoded string in one line. return ''.join(headerstr.splitlines()), 'us-ascii'
def buildEmailMessage(from_url, to_url, msg=None, subject=None, attachment_list=None, extra_headers=None, additional_headers=None, cc_url=None, bcc_url=None): """ Builds a mail message which is ready to be sent by Zope MailHost. * attachment_list is a list of dictionaries with those keys: - name : name of the attachment, - content: data of the attachment - mime_type: mime-type corresponding to the attachment * extra_headers is a dictionary of custom headers to add to the email. "X-" prefix is automatically added to those headers. * additional_headers is similar to extra_headers, but no prefix is added. """ if attachment_list == None: # Create non multi-part MIME message. message = MIMEText(msg, _charset='utf-8') attachment_list = [] else: # Create multi-part MIME message. message = MIMEMultipart() message.preamble = "If you can read this, your mailreader\n" \ "can not handle multi-part messages!\n" message.attach(MIMEText(msg, _charset='utf-8')) if extra_headers: for key, value in extra_headers.items(): message.add_header('X-%s' % key, value) if additional_headers: for key, value in additional_headers.items(): message.add_header(key, value) if subject: message.add_header('Subject', make_header([(subject, 'utf-8')]).encode()) if from_url: message.add_header('From', from_url) if to_url: message.add_header('To', to_url) if cc_url: message.add_header('Cc', cc_url) if bcc_url: message.add_header('Bcc', bcc_url) for attachment in attachment_list: attachment_name = attachment.get('name', '') attachment_name = attachment_name or '' # Prevent None params # try to guess the mime type if not attachment.has_key('mime_type'): mime_type, encoding = guess_type( attachment_name ) if mime_type is not None: attachment['mime_type'] = mime_type else: attachment['mime_type'] = 'application/octet-stream' # attach it if attachment['mime_type'] == 'text/plain': part = MIMEText(attachment['content'], _charset='utf-8') else: major, minor = attachment['mime_type'].split('/', 1) if major == 'text': part = MIMEText(attachment['content'], _subtype=minor) elif major == 'image': part = MIMEImage(attachment['content'], _subtype=minor) elif major == 'audio': part = MIMEAudio(attachment['content'], _subtype=minor) else: # encode non-plaintext attachment in base64 part = MIMEBase(major, minor) part.set_payload(attachment['content']) Encoders.encode_base64(part) part.add_header('Content-Disposition', 'attachment', filename=attachment_name) part.add_header('Content-ID', '<%s>' % \ ''.join(['%s' % ord(i) for i in attachment_name])) message.attach(part) return message
def _process_utf8(self, kw): # sort out what encoding we're going to use encoding = kw.get( 'encoding', self.getProperty('encoding', BaseMailTemplate.default_encoding)) text = self.__class__.__bases__[1].__call__(self, **kw) # ZPT adds newline at the end, but it breaks backward compatibility. # So I remove it. if text and text[-1] == '\n': text = text[:-1] if not self.html() and isinstance(text, unicode): text = text.encode(encoding, 'replace') # now turn the result into a MIMEText object msg = BaseMailTemplate.MIMEText(text.replace('\r', ''), self.content_type.split('/')[1], encoding) # sort out what headers and addresses we're going to use headers = {} values = {} # headers from the headers property for header in getattr(self, 'headers', ()): name, value = header.split(':', 1) headers[name] = value # headers from the headers parameter headers_param = kw.get('headers', {}) headers.update(headers_param) # values and some specific headers for key, header in (('mfrom', 'From'), ('mto', 'To'), ('mcc', 'Cc'), ('mbcc', 'Bcc'), ('subject', 'Subject')): value = kw.get( key, headers_param.get(header, getattr(self, key, headers.get(header)))) if value is not None: values[key] = value # turn some sequences in coma-seperated strings if isinstance(value, (tuple, list)): value = ', '.join(value) # make sure we have no unicode headers if isinstance(value, unicode): value = value.encode(encoding) if key == 'subject': value = make_header([(value, 'utf-8')]).encode() headers[header] = value # check required values have been supplied errors = [] for param in ('mfrom', 'mto', 'subject'): if not values.get(param): errors.append(param) if errors: raise TypeError( 'The following parameters were required by not specified: ' + (', '.join(errors))) # add date header headers['Date'] = BaseMailTemplate.DateTime().rfc822() # add message-id header headers['Message-ID'] = make_msgid() # turn headers into an ordered list for predictable header order keys = headers.keys() keys.sort() return msg, values, [(key, headers[key]) for key in keys]
def getSubject(msg): """ get mail subject """ return make_header(decode_header(msg.get('Subject').strip())).__unicode__()
def _process_utf8(self,kw): # sort out what encoding we're going to use encoding = kw.get('encoding', self.getProperty('encoding', BaseMailTemplate.default_encoding)) text = self.__class__.__bases__[1].__call__(self,**kw) # ZPT adds newline at the end, but it breaks backward compatibility. # So I remove it. if text and text[-1]=='\n': text = text[:-1] if not self.html() and isinstance(text, unicode): text = text.encode(encoding,'replace') # now turn the result into a MIMEText object msg = BaseMailTemplate.MIMEText( text.replace('\r',''), self.content_type.split('/')[1], encoding ) # sort out what headers and addresses we're going to use headers = {} values = {} # headers from the headers property for header in getattr(self,'headers',()): name,value = header.split(':',1) headers[name]=value # headers from the headers parameter headers_param = kw.get('headers',{}) headers.update(headers_param) # values and some specific headers for key,header in (('mfrom','From'), ('mto','To'), ('mcc','Cc'), ('mbcc','Bcc'), ('subject','Subject')): value = kw.get(key, headers_param.get(header, getattr(self, key, headers.get(header)))) if value is not None: values[key]=value # turn some sequences in coma-seperated strings if isinstance(value, (tuple, list)): value = ', '.join(value) # make sure we have no unicode headers if isinstance(value,unicode): value = value.encode(encoding) if key=='subject': value = make_header([(value, 'utf-8')]).encode() headers[header]=value # check required values have been supplied errors = [] for param in ('mfrom','mto'): if not values.get(param): errors.append(param) if errors: raise TypeError( 'The following parameters were required by not specified: '+( ', '.join(errors) )) # add date header headers['Date']=BaseMailTemplate.DateTime().rfc822() # add message-id header headers['Message-ID']=make_msgid() # turn headers into an ordered list for predictable header order keys = headers.keys() keys.sort() return msg,values,[(key,headers[key]) for key in keys]
def process(res, args): mlist = res.mlist digest = None password = None address = None realname = None # Parse the args argnum = 0 for arg in args: if arg.lower().startswith('address='): address = arg[8:] elif argnum == 0: password = arg elif argnum == 1: if arg.lower() not in ('digest', 'nodigest'): res.results.append(_('Bad digest specifier: %(arg)s')) return STOP if arg.lower() == 'digest': digest = 1 else: digest = 0 else: res.results.append(_('Usage:')) res.results.append(gethelp(mlist)) return STOP argnum += 1 # Fix the password/digest issue if (digest is None and password and password.lower() in ('digest', 'nodigest')): if password.lower() == 'digest': digest = 1 else: digest = 0 password = None # Fill in empty defaults if digest is None: digest = mlist.digest_is_default if password is None: password = Utils.MakeRandomPassword() if address is None: realname, address = parseaddr(res.msg['from']) if not address: # Fall back to the sender address address = res.msg.get_sender() if not address: res.results.append(_('No valid address found to subscribe')) return STOP # Watch for encoded names try: h = make_header(decode_header(realname)) # BAW: in Python 2.2, use just unicode(h) realname = h.__unicode__() except UnicodeError: realname = u'' # Coerce to byte string if uh contains only ascii try: realname = realname.encode('us-ascii') except UnicodeError: pass # Create the UserDesc record and do a non-approved subscription listowner = mlist.GetOwnerEmail() userdesc = UserDesc(address, realname, password, digest) remote = res.msg.get_sender() try: mlist.AddMember(userdesc, remote) except Errors.MembershipIsBanned: res.results.append( _("""\ The email address you supplied is banned from this mailing list. If you think this restriction is erroneous, please contact the list owners at %(listowner)s.""")) return STOP except Errors.MMBadEmailError: res.results.append( _("""\ Mailman won't accept the given email address as a valid address. (E.g. it must have an @ in it.)""")) return STOP except Errors.MMHostileAddress: res.results.append( _("""\ Your subscription is not allowed because the email address you gave is insecure.""")) return STOP except Errors.MMAlreadyAMember: res.results.append(_('You are already subscribed!')) return STOP except Errors.MMCantDigestError: res.results.append( _('No one can subscribe to the digest of this list!')) return STOP except Errors.MMMustDigestError: res.results.append(_('This list only supports digest subscriptions!')) return STOP except Errors.MMSubscribeNeedsConfirmation: # We don't need to respond /and/ send a confirmation message. res.respond = 0 except Errors.MMNeedApproval: res.results.append( _("""\ Your subscription request has been forwarded to the list administrator at %(listowner)s for review.""")) else: # Everything is a-ok res.results.append(_('Subscription request succeeded.'))
if not features and not args: usage("Require at least one feature (-f) arg or one message file") return 1 if not features: # extract significant tokens from each message and identify # where they came from for f in args: for msg in getmbox(f): evidence = msg.get("X-Spambayes-Evidence", "") evidence = re.sub(r"\s+", " ", evidence) l = [e.rsplit(": ", 1)[0] for e in evidence.split("; ")[2:]] for s in l: try: s = make_header(decode_header(s)).__unicode__() except: s = unicode(s, 'us-ascii', 'replace') features.add(s) if not features: usage("No X-Spambayes-Evidence headers found") return 1 if spamfile is not None: spamfile = file(spamfile, "w") if hamfile is not None: hamfile = file(hamfile, "w") extractmessages(features, mapd, hamfile, spamfile) if __name__ == "__main__":
def getSubject(msg): """ get mail subject """ return make_header( decode_header(msg.get('Subject').strip())).__unicode__()
def process(res, args): mlist = res.mlist digest = None password = None address = None realname = None # Parse the args argnum = 0 for arg in args: if arg.lower().startswith('address='): address = arg[8:] elif argnum == 0: password = arg elif argnum == 1: if arg.lower() not in ('digest', 'nodigest'): res.results.append(_('Bad digest specifier: %(arg)s')) return STOP if arg.lower() == 'digest': digest = 1 else: digest = 0 else: res.results.append(_('Usage:')) res.results.append(gethelp(mlist)) return STOP argnum += 1 # Fix the password/digest issue if (digest is None and password and password.lower() in ('digest', 'nodigest')): if password.lower() == 'digest': digest = 1 else: digest = 0 password = None # Fill in empty defaults if digest is None: digest = mlist.digest_is_default if password is None: password = Utils.MakeRandomPassword() if address is None: realname, address = parseaddr(res.msg['from']) if not address: # Fall back to the sender address address = res.msg.get_sender() if not address: res.results.append(_('No valid address found to subscribe')) return STOP # Watch for encoded names try: h = make_header(decode_header(realname)) # BAW: in Python 2.2, use just unicode(h) realname = h.__unicode__() except UnicodeError: realname = u'' # Coerce to byte string if uh contains only ascii try: realname = realname.encode('us-ascii') except UnicodeError: pass # Create the UserDesc record and do a non-approved subscription listowner = mlist.GetOwnerEmail() userdesc = UserDesc(address, realname, password, digest) remote = res.msg.get_sender() try: mlist.AddMember(userdesc, remote) except Errors.MembershipIsBanned: res.results.append(_("""\ The email address you supplied is banned from this mailing list. If you think this restriction is erroneous, please contact the list owners at %(listowner)s.""")) return STOP except Errors.MMBadEmailError: res.results.append(_("""\ Mailman won't accept the given email address as a valid address. (E.g. it must have an @ in it.)""")) return STOP except Errors.MMHostileAddress: res.results.append(_("""\ Your subscription is not allowed because the email address you gave is insecure.""")) return STOP except Errors.MMAlreadyAMember: res.results.append(_('You are already subscribed!')) return STOP except Errors.MMCantDigestError: res.results.append( _('No one can subscribe to the digest of this list!')) return STOP except Errors.MMMustDigestError: res.results.append(_('This list only supports digest subscriptions!')) return STOP except Errors.MMSubscribeNeedsConfirmation: # We don't need to respond /and/ send a confirmation message. res.respond = 0 except Errors.MMNeedApproval: res.results.append(_("""\ Your subscription request has been forwarded to the list administrator at %(listowner)s for review.""")) else: # Everything is a-ok res.results.append(_('Subscription request succeeded.'))