Example #1
0
    def send(self, subject, message, attach=[]):
        # Create message
        msg = MIMEMultipart()
        msg.set_unixfrom('author')
        msg['To'] = email.utils.formataddr(('Recipient', self.to_email))
        msg['From'] = email.utils.formataddr(('Author', '*****@*****.**'))
        msg['Subject'] = subject
        msg.attach(MIMEText(message))

        try:
            self.server.set_debuglevel(False)

            # identify ourselves, prompting server for supported features
            self.server.ehlo()

            # If we can encrypt this session, do it
            if self.server.has_extn('STARTTLS'):
                self.server.starttls()
                self.server.ehlo()  # re-identify ourselves over TLS connection

            # Attach files, if we have anything
            for atta in attach:
                part = MIMEBase('application', "octet-stream")
                part.set_payload(open(atta, "rb").read())
                Encoders.encode_base64(part)
                part.add_header(
                    'Content-Disposition',
                    'attachment; filename="%s"' % os.path.basename(atta))
                msg.attach(part)

            self.server.login(self.username, self.password)
            self.server.sendmail('*****@*****.**', [self.to_email],
                                 msg.as_string())
        finally:
            self.server.quit()
    def _convert_to_mbox_msg(self, msg):
        file_ids = list(msg.objectIds('File'))
        encoding = "utf-8"

        # true only if we have attachments
        if file_ids:
            enc_msg = MIMEMultipart()
            txt = MIMEText(msg.body.encode(encoding))
            enc_msg.attach(txt)
        else:
            enc_msg = Message()
            enc_msg.set_payload(msg.body.encode(encoding))

        enc_msg['From'] = encode_header(msg.from_addr, encoding)
        enc_msg['To'] = encode_header(self.context.mailto, encoding)
        enc_msg['Subject'] = encode_header(msg.subject, encoding).replace("\n", " ").strip()
        enc_msg['Date'] = encode_header(str(msg.date), encoding)
        enc_msg['Message-id'] = encode_header(msg.message_id, encoding)
        if msg.references:
            enc_msg['References'] = encode_header(" ".join(msg.references), encoding)
        if msg.in_reply_to:
            enc_msg['In-reply-to'] = encode_header(msg.in_reply_to, encoding)
                                    
        ctime = str(msg.date)
        enc_msg.set_unixfrom("From %s %s" % (parseaddr(msg.from_addr)[1], ctime))

        for file_id in file_ids:
            file = msg._getOb(file_id)
            data = file.data
            if not isinstance(data, basestring):
                data = str(data)
            content_type = file.getContentType()
            if content_type == 'message/rfc822':
                attachment = message_from_string(data)
            else:
                attachment = Message()
                attachment.add_header('Content-Disposition', 'attachment', filename=file.title)
                attachment.add_header('Content-Type', content_type)
                attachment.set_payload(data)
            enc_msg.attach(attachment)

        try:
            retval = enc_msg.as_string(unixfrom=True)
        except TypeError, e:
            raise
Example #3
0
def parse_and_deliver(maildir, url, statedir):
    feedhandle = None
    headers = None
    # first check if we know about this feed already
    feeddb = dbm.open(os.path.join(statedir, "feeds"), "c")
    if feeddb.has_key(url):
        data = feeddb[url]
        data = cgi.parse_qs(data)
        response = open_url("HEAD", url)
        headers = None
        if response:
            headers = response.getheaders()
        ischanged = False
        try:
            for header in headers:
                if header[0] == "content-length":
                    if header[1] != data["content-length"][0]:
                        ischanged = True
                elif header[0] == "etag":
                    if header[1] != data["etag"][0]:
                        ischanged = True
                elif header[0] == "last-modified":
                    if header[1] != data["last-modified"][0]:
                        ischanged = True
                elif header[0] == "content-md5":
                    if header[1] != data["content-md5"][0]:
                        ischanged = True
        except:
            ischanged = True
        if ischanged:
            response = open_url("GET", url)
            if response != None:
                headers = response.getheaders()
                feedhandle = response
            else:
                sys.stderr.write("Failed to fetch feed: %s\n" % (url))
                return
        else:
            return  # don't need to do anything, nothings changed.
    else:
        response = open_url("GET", url)
        if response != None:
            headers = response.getheaders()
            feedhandle = response
        else:
            sys.stderr.write("Failed to fetch feed: %s\n" % (url))
            return

    fp = feedparser.parse(feedhandle)
    db = dbm.open(os.path.join(statedir, "seen"), "c")
    for item in fp["items"]:
        # have we seen it before?
        # need to work out what the content is first...

        if item.has_key("content"):
            content = item["content"][0]["value"]
        else:
            if item.has_key("description"):
                content = item["description"]
            else:
                content = u""

        md5sum = md5.md5(content.encode("utf-8")).hexdigest()

        # make sure content is unicode encoded
        if not isinstance(content, unicode):
            cd_res = chardet.detect(content)
            chrset = cd_res["encoding"]
            print "detected charset %s for item %s" % (chrset, item["link"])
            content = content.decode(chrset)

        prevmessageid = None

        db_guid_key = None
        db_link_key = (url + u"|" + item["link"]).encode("utf-8")

        # check if there's a guid too - if that exists and we match the md5,
        # return
        if item.has_key("guid"):
            db_guid_key = (url + u"|" + item["guid"]).encode("utf-8")
            if db.has_key(db_guid_key):
                data = db[db_guid_key]
                data = cgi.parse_qs(data)
                if data["contentmd5"][0] == md5sum:
                    continue

        if db.has_key(db_link_key):
            data = db[db_link_key]
            data = cgi.parse_qs(data)
            if data.has_key("message-id"):
                prevmessageid = data["message-id"][0]
            if data["contentmd5"][0] == md5sum:
                continue

        try:
            author = item["author"]
        except:
            author = url

        # create a basic email message
        msg = MIMEMultipart("alternative")
        messageid = (
            "<"
            + datetime.datetime.now().strftime("%Y%m%d%H%M")
            + "."
            + "".join([random.choice(string.ascii_letters + string.digits) for a in range(0, 6)])
            + "@"
            + socket.gethostname()
            + ">"
        )
        msg.add_header("Message-ID", messageid)
        msg.set_unixfrom('"%s" <rss2maildir@localhost>' % (url))
        msg.add_header("From", '"%s" <rss2maildir@localhost>' % (author.encode("utf-8")))
        msg.add_header("To", '"%s" <rss2maildir@localhost>' % (url.encode("utf-8")))
        if prevmessageid:
            msg.add_header("References", prevmessageid)
        createddate = datetime.datetime.now().strftime("%a, %e %b %Y %T -0000")
        try:
            createddate = datetime.datetime(*item["updated_parsed"][0:6]).strftime("%a, %e %b %Y %T -0000")
        except:
            pass
        msg.add_header("Date", createddate)
        msg.add_header("X-rss2maildir-rundate", datetime.datetime.now().strftime("%a, %e %b %Y %T -0000"))
        title = html.fromstring(item["title"]).text
        title = re.sub(u"<", u"&lt;", title)
        title = re.sub(u">", u"&gt;", title)
        msg.add_header("Subject", str(Header(title.encode("utf-8"), "utf-8")))
        msg.set_default_type("text/plain")

        htmlcontent = content.encode("utf-8")
        htmlcontent = "%s\n\n<p>Item URL: <a href='%s'>%s</a></p>" % (content, item["link"], item["link"])
        htmlpart = MIMEText(htmlcontent.encode("utf-8"), "html", "utf-8")
        msg.attach(htmlpart)

        # start by working out the filename we should be writting to, we do
        # this following the normal maildir style rules
        fname = (
            str(os.getpid())
            + "."
            + socket.gethostname()
            + "."
            + "".join([random.choice(string.ascii_letters + string.digits) for a in range(0, 10)])
            + "."
            + datetime.datetime.now().strftime("%s")
        )
        fn = os.path.join(maildir, "tmp", fname)
        fh = open(fn, "w")
        fh.write(msg.as_string())
        fh.close()
        # now move it in to the new directory
        newfn = os.path.join(maildir, "new", fname)
        os.link(fn, newfn)
        os.unlink(fn)

        # now add to the database about the item
        if prevmessageid:
            messageid = prevmessageid + " " + messageid
        if item.has_key("guid") and item["guid"] != item["link"]:
            data = urllib.urlencode((("message-id", messageid), ("created", createddate), ("contentmd5", md5sum)))
            db[db_guid_key] = data
            try:
                data = db[db_link_key]
                data = cgi.parse_qs(data)
                newdata = urllib.urlencode(
                    (("message-id", messageid), ("created", data["created"][0]), ("contentmd5", data["contentmd5"][0]))
                )
                db[db_link_key] = newdata
            except:
                db[db_link_key] = data
        else:
            data = urllib.urlencode((("message-id", messageid), ("created", createddate), ("contentmd5", md5sum)))
            db[db_link_key] = data

    if headers:
        data = []
        for header in headers:
            if header[0] in ["content-md5", "etag", "last-modified", "content-length"]:
                data.append((header[0], header[1]))
        if len(data) > 0:
            data = urllib.urlencode(data)
            feeddb[url] = data

    db.close()
    feeddb.close()