def sendmessage(self,to='',subj='',content='',attach=None): msg = Message() COMMASPACE = ', ' if not to: to=self.to to=map(self.addsuff,to) print to if not subj: subj=self.subj if not content: content=self.subj msg = MIMEMultipart() msg['From'] = self.emailfrom if self.cc: msg['CC'] = self.cc msg['To'] =COMMASPACE.join(to) msg['Subject'] = Header(subj,'utf-8') msg['Date'] = email.Utils.formatdate() # msg.set_payload(content) if not attach: msg.set_payload(content) else: msg.attach(content) msg.attach(attach) try: failed = self.server.sendmail(self.emailfrom,to,msg.as_string()) # may also raise exc except Exception ,ex: print Exception,ex return 'Error - send failed'
def notifyModerators(self, moderators, article): """ Send an article to a list of group moderators to be moderated. @param moderators: A C{list} of C{str} giving RFC 2821 addresses of group moderators to notify. @param article: The article requiring moderation. @type article: L{Article} @return: A L{Deferred} which fires with the result of sending the email. """ # Moderated postings go through as long as they have an Approved # header, regardless of what the value is group = article.getHeader('Newsgroups') subject = article.getHeader('Subject') if self._sender is None: # This case should really go away. This isn't a good default. sender = 'twisted-news@' + socket.gethostname() else: sender = self._sender msg = Message() msg['Message-ID'] = smtp.messageid() msg['From'] = sender msg['To'] = ', '.join(moderators) msg['Subject'] = 'Moderate new %s message: %s' % (group, subject) msg['Content-Type'] = 'message/rfc822' payload = Message() for header, value in article.headers.values(): payload.add_header(header, value) payload.set_payload(article.body) msg.attach(payload) out = StringIO.StringIO() gen = Generator(out, False) gen.flatten(msg) msg = out.getvalue() return self.sendmail(self._mailhost, sender, moderators, msg)
def sendAggregateMail(self, cachedResults): # cachedResults is a list of dicts: {'name':name, 'build':build, 'results':results} projectName = self.status.getProjectName() # build will be the same for all messages, so just use the first one build = cachedResults[0]['build'] source = build.getSourceStamp().revision # Delimiting wht "," causes email subject line to contain a TAB character for some reason blamelist = "|".join(build.getResponsibleUsers()) p = re.compile( " <[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?>" ) blamelist = p.sub("", blamelist) slaves = [] results = [] for result in cachedResults: slaves.append(result['name']) results.append(result['results']) text = '' text += "Blame: %s\n" % blamelist text += "Slave(s): %s\n" % ', '.join(slaves) text += "Branch: %s\n" % self.branch text += " %s\n" % self.status.getBuildbotURL() text += "Change: %s\n" % source # TODO - handle results other than FAILURE text += "Status: fail" text += "\n" if FAILURE in results: text += "Log(s) of failed build steps:\n" for result in cachedResults: if result['results'] == FAILURE: build = result['build'] text += " Slave: %s\n" % result['name'] for step in build.getSteps(): if step.getResults()[0] == FAILURE: text += " %s\n" % ''.join( step.getResults()[1]) buildurl = "%sbuilders/%s/builds/%d" % ( self.status.getBuildbotURL(), result['name'], build.getNumber()) text += " %s/steps/%s/logs/stdio\n" % ( buildurl, ''.join(step.getResults()[1])) text += "\n" failSteps, buildinfo = self.getBuildsStatusFileinfo( build, blamelist, source) # add previous failures to email if failSteps: text += ' Buildsteps that were failing before this build:\n' for step in failSteps: text += ' %s Revision: %s Blamelist: %s\n' % ( step, buildinfo[step]['revision'], buildinfo[step]['blamelist']) text += "\n" m = Message() m.set_payload(text) m['Date'] = formatdate(localtime=True) m['Subject'] = self.subject % { 'result': 'fail', 'blamelist': blamelist, 'branch': self.branch, 'src': source, } m['From'] = self.fromaddr # m['To'] is added later if self.addLogs: for result in cachedResults: build = result['build'] for log in build.getLogs(): name = "%s.%s" % (log.getStep().getName(), log.getName()) a = MIMEText(log.getText()) a.add_header('Content-Disposition', "attachment", filename=name) m.attach(a) # now, who is this message going to? dl = [] recipients = self.extraRecipients[:] if self.sendToInterestedUsers and self.lookup: for u in build.getInterestedUsers(): d = defer.maybeDeferred(self.lookup.getAddress, u) d.addCallback(recipients.append) dl.append(d) d = defer.DeferredList(dl) d.addCallback(self._gotRecipients, recipients, m) return d
class GPGEmail(SimpleEmail): """Třída pro vytvoření a odeslaní jednoduchého kryptovaného mailu.""" ERR_GPG_MODULE = _(u"Could not import Python GnuPG module") ERR_GPG_INSTANCE = _(u"Could not create GPG instance") ERR_GPG_KEYRING = _(u"Could not create a temporary GPG keyring") ERR_GPG_OUTPUT = _(u"GPG process did not return string.") def __init__(self, to, from_, subject, content, key, html=False, smtp='localhost', charset='iso-8859-2'): """Inicializuj instanci. to -- adresa příjemce (zatím podporujeme jen jednoho příjemce) from_ -- adresa odesílatele subject -- předmět zprávy (může obsahovat buď řetězec nebo unicode content -- vlastní obsah zprávy key -- veřejný klíč, kterým má být zpráva zakryptována html -- příznak, zda obsah je html smtp -- adresa odesílacího serveru charset -- v případě, že content není v unicode, je zde uveden charset pro content """ super(GPGEmail, self).__init__(to, from_, subject, content, html=html, smtp=smtp, charset=charset) self.key = key def _create_message(self): """Return basic instance of Message.""" self.msg = Message() def _setup_gpg(self): "Setup GPG process. Returns initialized gpg instance." try: import tempfile import GnuPGInterface except: self._error_msg = self.ERR_GPG_MODULE return None try: gpg = GnuPGInterface.GnuPG() except: self._error_msg = self.ERR_GPG_INSTANCE return None try: keyring = tempfile.mkstemp()[1] except: self._error_msg = self.ERR_GPG_KEYRING return None gpg.options.armor = 1 gpg.options.meta_interactive = 0 gpg.options.extra_args.append('--no-secmem-warning') for o in ('--always-trust', '--no-default-keyring', '--keyring=%s' % keyring): gpg.options.extra_args.append(o) proc = gpg.run(['--import'], create_fhs=['stdin', 'stderr']) proc.handles['stdin'].write(self.key) proc.handles['stdin'].close() proc.handles['stderr'].read() proc.handles['stderr'].close() proc.wait() return gpg def _gpg_encrypt_content(self): "Encrypt the content." gpg = self._setup_gpg() if not gpg: raise pytis.util.ProgramError(self._error_msg) if isinstance(self.to, basestring): to = (self.to, ) elif isinstance(self.to, unicode): # Unicode arguments are problem for GPG process, so we will convert them to UTF-8 to = [] for t in self.to: to.append(t.encode('UTF-8')) else: to = self.to content = self.get_content_text(self.content, html=self.html, charset=self.charset) gpg.options.recipients = to # a list or tuple! proc = gpg.run(['--encrypt'], create_fhs=['stdin', 'stdout']) proc.handles['stdin'].write(content.as_string()) proc.handles['stdin'].close() output = proc.handles['stdout'].read() proc.handles['stdout'].close() proc.wait() success = True if not isinstance(output, basestring): success = False # BUG: There is no `keyring' defined here so the following # statement is effectively void: try: os.remove(keyring) except: pass if not success: raise pytis.util.ProgramError(self.ERR_GPG_OUTPUT) else: return output def create_headers(self): super(GPGEmail, self).create_headers() self.msg["Mime-version"] = "1.0" self.msg["Content-type"] = "Multipart/encrypted" self.msg["Content-transfer-encoding"] = "8bit" self.msg.preamble = "This is an OpenPGP/MIME encrypted message (RFC 2440 and 3156)" def create_content(self): # Part 1 firstSubMsg = email.Message.Message() firstSubMsg["Content-Type"] = "application/pgp-encrypted" firstSubMsg["Content-Description"] = "PGP/MIME version identification" firstSubMsg.set_payload("Version: 1\n") # Part 2 if self.html: filename = 'content.html.pgp' else: filename = 'content.txt.pgp' encrypted = self._gpg_encrypt_content() secondSubMsg = email.Message.Message() secondSubMsg.add_header("Content-Type", "application/octet-stream", name=filename) secondSubMsg.add_header("Content-Description", "OpenPGP encrypted message") secondSubMsg.add_header("Content-Disposition", "inline", filename=filename) secondSubMsg.set_payload(encrypted) # Přidání částí do main self.msg.attach(firstSubMsg) self.msg.attach(secondSubMsg)
def sendAggregateMail(self, cachedResults): # cachedResults is a list of dicts: {'name':name, 'build':build, 'results':results} projectName = self.status.getProjectName() # build will be the same for all messages, so just use the first one build = cachedResults[0]['build'] source = build.getSourceStamp().revision # Delimiting wht "," causes email subject line to contain a TAB character for some reason blamelist = "|".join(build.getResponsibleUsers()) p = re.compile(" <[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?>") blamelist = p.sub("", blamelist) slaves = [] results = [] for result in cachedResults: slaves.append(result['name']) results.append(result['results']) text = '' text += "Blame: %s\n" % blamelist text += "Slave(s): %s\n" % ', '.join(slaves) text += "Branch: %s\n" % self.branch text += " %s\n" % self.status.getBuildbotURL() text += "Change: %s\n" % source # TODO - handle results other than FAILURE text += "Status: fail" text += "\n" if FAILURE in results: text += "Log(s) of failed build steps:\n" for result in cachedResults: if result['results'] == FAILURE: build = result['build'] text += " Slave: %s\n" % result['name'] for step in build.getSteps(): if step.getResults()[0] == FAILURE: text += " %s\n" % ''.join(step.getResults()[1]) buildurl = "%sbuilders/%s/builds/%d" % (self.status.getBuildbotURL(),result['name'],build.getNumber()) text += " %s/steps/%s/logs/stdio\n" % (buildurl,''.join(step.getResults()[1])) text += "\n" failSteps, buildinfo = self.getBuildsStatusFileinfo(build, blamelist, source) # add previous failures to email if failSteps: text += ' Buildsteps that were failing before this build:\n' for step in failSteps: text += ' %s Revision: %s Blamelist: %s\n' % (step, buildinfo[step]['revision'], buildinfo[step]['blamelist']) text += "\n" m = Message() m.set_payload(text) m['Date'] = formatdate(localtime=True) m['Subject'] = self.subject % { 'result': 'fail', 'blamelist': blamelist, 'branch': self.branch, 'src': source, } m['From'] = self.fromaddr # m['To'] is added later if self.addLogs: for result in cachedResults: build = result['build'] for log in build.getLogs(): name = "%s.%s" % (log.getStep().getName(), log.getName()) a = MIMEText(log.getText()) a.add_header('Content-Disposition', "attachment", filename=name) m.attach(a) # now, who is this message going to? dl = [] recipients = self.extraRecipients[:] if self.sendToInterestedUsers and self.lookup: for u in build.getInterestedUsers(): d = defer.maybeDeferred(self.lookup.getAddress, u) d.addCallback(recipients.append) dl.append(d) d = defer.DeferredList(dl) d.addCallback(self._gotRecipients, recipients, m) return d
def sendAggregateMail(self, cachedResults): # cachedResults is a list of dicts: {'name':name, 'build':build, 'results':results} projectName = self.status.getProjectName() # build will be the same for all messages, so just use the first one build = cachedResults[0]['build'] sourcestamp = build.getSourceStamp() source = sourcestamp.revision # Delimiting wht "," causes email subject line to contain a TAB character for some reason blamelist = "|".join(build.getResponsibleUsers()) p = re.compile(" <[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?>") blamelist = p.sub("", blamelist) slaves = [] results = [] for result in cachedResults: slaves.append(result['name']) results.append(result['results']) # If _any_ build failed, then we do not send this email (failure emails are dealt with separately) if FAILURE in results: return text = '' text += 'Congratulations, your %s build has passed all acceptance tests!\n' % self.branch text += '\n' text += self.getChangesText(sourcestamp.changes) m = Message() m.set_payload(text) m['Date'] = formatdate(localtime=True) m['Subject'] = self.subject % { 'result': 'pass', 'blamelist': blamelist, 'branch': self.branch, 'src': source, } m['From'] = self.fromaddr # m['To'] is added later if self.addLogs: for result in cachedResults: build = result['build'] for log in build.getLogs(): name = "%s.%s" % (log.getStep().getName(), log.getName()) a = MIMEText(log.getText()) a.add_header('Content-Disposition', "attachment", filename=name) m.attach(a) # now, who is this message going to? dl = [] recipients = self.extraRecipients[:] if self.sendToInterestedUsers and self.lookup: for u in build.getInterestedUsers(): d = defer.maybeDeferred(self.lookup.getAddress, u) d.addCallback(recipients.append) dl.append(d) d = defer.DeferredList(dl) d.addCallback(self._gotRecipients, recipients, m) return d
def buildMessage(self, name, build, results): projectName = self.status.getProjectName() sourcestamp = build.getSourceStamp() source = sourcestamp.revision buildurl = "%sbuilders/%s/builds/%d" % (self.status.getBuildbotURL(),name,build.getNumber()) # Delimiting wht "," causes email subject line to contain a TAB character for some reason blamelist = "|".join(build.getResponsibleUsers()) p = re.compile(" <[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?>") blamelist = p.sub("", blamelist) res = "pass" if results == FAILURE: res = "fail" text = '' text += 'Slave: %s\n' % name text += 'Branch: %s\n' % self.branch text += self.getChangesText(sourcestamp.changes) if results == FAILURE: text += "Log(s) of failed build steps:\n" for step in build.getSteps(): if step.getResults()[0] == FAILURE: text += " %s\n" % ''.join(step.getResults()[1]) text += " %s/steps/%s/logs/stdio\n" % (buildurl,''.join(step.getResults()[1])) text += "\n" failSteps, buildinfo = self.getBuildsStatusFileinfo(build, blamelist, source) # add previous failures to email if failSteps: text += 'Buildsteps that were failing before this build:\n' for step in failSteps: text += ' %s Revision: %s Blamelist: %s\n' % (step, buildinfo[step]['revision'], buildinfo[step]['blamelist']) text += "\n" m = Message() m.set_payload(text) m['Date'] = formatdate(localtime=True) m['Subject'] = self.subject % { 'result': res, 'blamelist': blamelist, 'branch': self.branch, 'src': source, } m['From'] = self.fromaddr # m['To'] is added later if self.addLogs: for log in build.getLogs(): name = "%s.%s" % (log.getStep().getName(), log.getName()) a = MIMEText(log.getText()) a.add_header('Content-Disposition', "attachment", filename=name) m.attach(a) # now, who is this message going to? dl = [] recipients = self.extraRecipients[:] if self.sendToInterestedUsers and self.lookup: for u in build.getInterestedUsers(): d = defer.maybeDeferred(self.lookup.getAddress, u) d.addCallback(recipients.append) dl.append(d) d = defer.DeferredList(dl) d.addCallback(self._gotRecipients, recipients, m) return d
def sendAggregateMail(self, cachedResults): # cachedResults is a list of dicts: {'name':name, 'build':build, 'results':results} projectName = self.status.getProjectName() # build will be the same for all messages, so just use the first one build = cachedResults[0]['build'] sourcestamp = build.getSourceStamp() source = sourcestamp.revision # Delimiting wht "," causes email subject line to contain a TAB character for some reason blamelist = "|".join(build.getResponsibleUsers()) p = re.compile( " <[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?>" ) blamelist = p.sub("", blamelist) slaves = [] results = [] for result in cachedResults: slaves.append(result['name']) results.append(result['results']) # If _any_ build failed, then we do not send this email (failure emails are dealt with separately) if FAILURE in results: return text = '' text += 'Congratulations, your %s build has passed all acceptance tests!\n' % self.branch text += '\n' text += self.getChangesText(sourcestamp.changes) m = Message() m.set_payload(text) m['Date'] = formatdate(localtime=True) m['Subject'] = self.subject % { 'result': 'pass', 'blamelist': blamelist, 'branch': self.branch, 'src': source, } m['From'] = self.fromaddr # m['To'] is added later if self.addLogs: for result in cachedResults: build = result['build'] for log in build.getLogs(): name = "%s.%s" % (log.getStep().getName(), log.getName()) a = MIMEText(log.getText()) a.add_header('Content-Disposition', "attachment", filename=name) m.attach(a) # now, who is this message going to? dl = [] recipients = self.extraRecipients[:] if self.sendToInterestedUsers and self.lookup: for u in build.getInterestedUsers(): d = defer.maybeDeferred(self.lookup.getAddress, u) d.addCallback(recipients.append) dl.append(d) d = defer.DeferredList(dl) d.addCallback(self._gotRecipients, recipients, m) return d
def buildMessage(self, name, build, results): projectName = self.status.getProjectName() sourcestamp = build.getSourceStamp() source = sourcestamp.revision buildurl = "%sbuilders/%s/builds/%d" % (self.status.getBuildbotURL(), name, build.getNumber()) # Delimiting wht "," causes email subject line to contain a TAB character for some reason blamelist = "|".join(build.getResponsibleUsers()) p = re.compile( " <[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?>" ) blamelist = p.sub("", blamelist) res = "pass" if results == FAILURE: res = "fail" text = '' text += 'Slave: %s\n' % name text += 'Branch: %s\n' % self.branch text += self.getChangesText(sourcestamp.changes) if results == FAILURE: text += "Log(s) of failed build steps:\n" for step in build.getSteps(): if step.getResults()[0] == FAILURE: text += " %s\n" % ''.join(step.getResults()[1]) text += " %s/steps/%s/logs/stdio\n" % ( buildurl, ''.join(step.getResults()[1])) text += "\n" failSteps, buildinfo = self.getBuildsStatusFileinfo( build, blamelist, source) # add previous failures to email if failSteps: text += 'Buildsteps that were failing before this build:\n' for step in failSteps: text += ' %s Revision: %s Blamelist: %s\n' % ( step, buildinfo[step]['revision'], buildinfo[step]['blamelist']) text += "\n" m = Message() m.set_payload(text) m['Date'] = formatdate(localtime=True) m['Subject'] = self.subject % { 'result': res, 'blamelist': blamelist, 'branch': self.branch, 'src': source, } m['From'] = self.fromaddr # m['To'] is added later if self.addLogs: for log in build.getLogs(): name = "%s.%s" % (log.getStep().getName(), log.getName()) a = MIMEText(log.getText()) a.add_header('Content-Disposition', "attachment", filename=name) m.attach(a) # now, who is this message going to? dl = [] recipients = self.extraRecipients[:] if self.sendToInterestedUsers and self.lookup: for u in build.getInterestedUsers(): d = defer.maybeDeferred(self.lookup.getAddress, u) d.addCallback(recipients.append) dl.append(d) d = defer.DeferredList(dl) d.addCallback(self._gotRecipients, recipients, m) return d
class GPGEmail(SimpleEmail): """Třída pro vytvoření a odeslaní jednoduchého kryptovaného mailu.""" ERR_GPG_MODULE = _(u"Could not import Python GnuPG module") ERR_GPG_INSTANCE = _(u"Could not create GPG instance") ERR_GPG_KEYRING = _(u"Could not create a temporary GPG keyring") ERR_GPG_OUTPUT = _(u"GPG process did not return string.") def __init__(self, to, from_, subject, content, key, html=False, smtp='localhost', charset='iso-8859-2'): """Inicializuj instanci. to -- adresa příjemce (zatím podporujeme jen jednoho příjemce) from_ -- adresa odesílatele subject -- předmět zprávy (může obsahovat buď řetězec nebo unicode content -- vlastní obsah zprávy key -- veřejný klíč, kterým má být zpráva zakryptována html -- příznak, zda obsah je html smtp -- adresa odesílacího serveru charset -- v případě, že content není v unicode, je zde uveden charset pro content """ super(GPGEmail, self).__init__(to, from_, subject, content, html=html, smtp=smtp, charset=charset) self.key = key def _create_message(self): """Return basic instance of Message.""" self.msg = Message() def _setup_gpg(self): "Setup GPG process. Returns initialized gpg instance." try: import tempfile import GnuPGInterface except: self._error_msg = self.ERR_GPG_MODULE return None try: gpg = GnuPGInterface.GnuPG() except: self._error_msg = self.ERR_GPG_INSTANCE return None try: keyring = tempfile.mkstemp()[1] except: self._error_msg = self.ERR_GPG_KEYRING return None gpg.options.armor = 1 gpg.options.meta_interactive = 0 gpg.options.extra_args.append('--no-secmem-warning') for o in ('--always-trust', '--no-default-keyring', '--keyring=%s' % keyring): gpg.options.extra_args.append(o) proc = gpg.run(['--import'], create_fhs=['stdin', 'stderr']) proc.handles['stdin'].write(self.key) proc.handles['stdin'].close() proc.handles['stderr'].read() proc.handles['stderr'].close() proc.wait() return gpg def _gpg_encrypt_content(self): "Encrypt the content." gpg = self._setup_gpg() if not gpg: raise pytis.util.ProgramError(self._error_msg) if isinstance(self.to, basestring): to = (self.to,) elif isinstance(self.to, unicode): # Unicode arguments are problem for GPG process, so we will convert them to UTF-8 to = [] for t in self.to: to.append(t.encode('UTF-8')) else: to = self.to content = self.get_content_text(self.content, html=self.html, charset=self.charset) gpg.options.recipients = to # a list or tuple! proc = gpg.run(['--encrypt'], create_fhs=['stdin', 'stdout']) proc.handles['stdin'].write(content.as_string()) proc.handles['stdin'].close() output = proc.handles['stdout'].read() proc.handles['stdout'].close() proc.wait() success = True if not isinstance(output, basestring): success = False # BUG: There is no `keyring' defined here so the following # statement is effectively void: try: os.remove(keyring) except: pass if not success: raise pytis.util.ProgramError(self.ERR_GPG_OUTPUT) else: return output def create_headers(self): super(GPGEmail, self).create_headers() self.msg["Mime-version"] = "1.0" self.msg["Content-type"] = "Multipart/encrypted" self.msg["Content-transfer-encoding"] = "8bit" self.msg.preamble = "This is an OpenPGP/MIME encrypted message (RFC 2440 and 3156)" def create_content(self): # Part 1 firstSubMsg = email.Message.Message() firstSubMsg["Content-Type"] = "application/pgp-encrypted" firstSubMsg["Content-Description"] = "PGP/MIME version identification" firstSubMsg.set_payload("Version: 1\n") # Part 2 if self.html: filename = 'content.html.pgp' else: filename = 'content.txt.pgp' encrypted = self._gpg_encrypt_content() secondSubMsg = email.Message.Message() secondSubMsg.add_header("Content-Type", "application/octet-stream", name=filename) secondSubMsg.add_header("Content-Description", "OpenPGP encrypted message") secondSubMsg.add_header("Content-Disposition", "inline", filename=filename) secondSubMsg.set_payload(encrypted) # Přidání částí do main self.msg.attach(firstSubMsg) self.msg.attach(secondSubMsg)
def constructMessage(context, fields, charset='utf-8'): msg = Message() primary = [] # First get all headers, storing primary fields for later for name, field in fields: if IPrimaryField.providedBy(field): primary.append((name, field,)) break # marshaler = queryMultiAdapter((context, field,), IFieldMarshaler) # if marshaler is None: # LOG.debug("No marshaler found for field %s of %s" % (name, repr(context))) # continue # # try: # value = marshaler.marshal(charset, primary=False) # except ValueError, e: # LOG.debug("Marshaling of %s for %s failed: %s" % (name, repr(context), str(e))) # continue # # if value is None: # value = '' # elif not isinstance(value, str): # raise ValueError("Marshaler for field %s did not return a string" % name) # # if marshaler.ascii and '\n' not in value: # msg[name] = value # else: # msg[name] = Header(value, charset) # Then deal with the primary field # If there's a single primary field, we have a non-multipart message with # a string payload if len(primary) == 1: name, field = primary[0] marshaler = queryMultiAdapter((context, field,), IFieldMarshaler) # import pdb # pdb.set_trace() if marshaler is not None: contentType = marshaler.getContentType() payloadCharset = marshaler.getCharset(charset) # if contentType is not None: # msg.set_type(contentType) # # if payloadCharset is not None: # # using set_charset() would also add transfer encoding, # # which we don't want to do always # msg.set_param('charset', payloadCharset) value = marshaler.marshal(charset, primary=True) # import pdb # pdb.set_trace() if value is not None: msg.set_payload(value) # marshaler.postProcessMessage(msg) # Otherwise, we return a multipart message elif len(primary) > 1: msg.set_type('multipart/mixed') for name, field in primary: marshaler = queryMultiAdapter((context, field,), IFieldMarshaler) if marshaler is None: continue payload = Message() attach = False contentType = marshaler.getContentType() payloadCharset = marshaler.getCharset(charset) if contentType is not None: payload.set_type(contentType) attach = True if payloadCharset is not None: # using set_charset() would also add transfer encoding, # which we don't want to do always payload.set_param('charset', payloadCharset) attach = True value = marshaler.marshal(charset, primary=True) if value is not None: payload.set_payload(value) attach = True if attach: marshaler.postProcessMessage(payload) msg.attach(payload) return msg
class SmartMessage: """Uproszczony interfejs dla bibliotek Pythona, który potrafi tworzyæ wiadomoœci tekstowe i z za³¹cznikami MIME.""" def __init__(self, fromAddr, toAddrs, subject, body, enc='iso-8859-2'): """Zacznij od za³o¿enia, i¿ bêdzie to prosta wiadomoœæ tekstowa zgodna z RFC 2822 i bez MIME.""" self.msg = Message() self.msg.set_payload(body) self['Subject'] = subject self.setFrom(fromAddr) self.setTo(toAddrs) self.hasAttachments = False self.enc = enc def setFrom(self, fromAddr): "Ustawia adres nadawcy wiadomoœci." if not fromAddr or not type(fromAddr) == type(''): raise Exception, 'Wiadomoœæ musi mieæ jednego i tylko jednego nadawcê.' self['From'] = fromAddr def setTo(self, to): "Ustawia adresy osób, które maj¹ otrzymaæ wiadomoœæ." if not to: raise Exception, 'Wiadomoœæ musi mieæ co najmniej jednego odbiorcê.' self._addresses(to, 'To') #Dodatkowo przechowuj adresy jako listê. Byæ mo¿e #skorzysta z niej kod, który zajmie siê wysy³aniem wiadomoœci. self.to = to def setCc(self, cc): """Ustawia adresy osób, które maj¹ otrzymaæ kopiê wiadomoœc. choæ nie jest ona adresowana do nich w sposób bezpoœredni.""" self._addresses(cc, 'Cc') def addAttachment(self, attachment, filename, mimetype=None): "Do³¹cza do wiadomoœci wskazany plik." #Odgadnij g³ówny i dodatkowy typ MIME na podstawie nazwy pliku. if not mimetype: mimetype = mimetypes.guess_type(filename)[0] if not mimetype: raise Exception, "Nie uda³o siê okreœliæ typu MIME dla", filename if '/' in mimetype: major, minor = mimetype.split('/') else: major = mimetype minor = None #Wiadomoœæ by³a konstruowana z za³o¿eniem, i¿ bêdzie zawieraæ #tylko i wy³¹cznie tekst. Poniewa¿ wiem, ¿e bêdzie zawieraæ #co najmniej jeden za³¹cznik, musimy zmieniæ j¹ na wiadomoœæ #wieloczêœciow¹ i wkleiæ tekst jako pierwsz¹ czêœæ. if not self.hasAttachments: body = self.msg.get_payload() newMsg = MIMEMultipart() newMsg.attach(MIMEText(body, 'plain', self.enc)) #Skopiuj stare nag³ówki do nowego obiektu. for header, value in self.msg.items(): newMsg[header] = value self.msg = newMsg self.hasAttachments = True subMessage = MIMENonMultipart(major, minor, name=filename) subMessage.set_payload(attachment) #Zakoduj teksty jako quoted printable natomiast wszystkie #inne typy jako base64. if major == 'text': encoder = Encoders.encode_quopri else: encoder = Encoders.encode_base64 encoder(subMessage) #Powi¹¿ fragment MIME z g³ówn¹ wiadomoœci¹. self.msg.attach(subMessage) def _addresses(self, addresses, key): """Ustawia zawartoœæ nag³ówka na podstawie listy przekazanych adresów.""" if hasattr(addresses, '__iter__'): addresses = ', '.join(addresses) self[key] = addresses #Kilka metod dodatkowych umo¿liwiaj¹cych traktowanie klasy w podobny #sposób, jak klasy Message lub MultipartMessage, stosuj¹c odpowiedni¹ #delegacjê poleceñ do tych klas. def __getitem__(self, key): "Zwróæ nag³ówek o podanym kluczu." return self.msg[key] def __setitem__(self, key, value): "Ustaw nag³ówek o wskazanej nazwie." self.msg[key] = value def __getattr__(self, key): return getattr(self.msg, key) def __str__(self): "Zwróæ tekstow¹ reprezentacjê wiadomoœci." return self.msg.as_string()