0

我有这个用于将原始电子邮件插入数据库的 python 脚本。不要问我为什么要将原始邮件插入数据库。

import sys
from DB import *
import email

full_msg = sys.stdin.readlines()
j =  ''.join(full_msg)
msg = email.message_from_string(j)

sql = '''INSERT INTO Email(Id, Message) VALUES (NULL, %s)'''
db = DB()
db.query(sql, (msg, ))

如果我能获得该消息的 uid 那就太好了,所以如果我从 db 中删除消息,我也可以在 imap 服务器上删除消息我的 uid。

我不想登录到 imap 服务器然后通过 uid 删除消息,因为我不知道用户密码,因为它是加密的。

我想获取例如 msg['Message-Id'] ,然后在用户 maildir 中为该 Message-Id grep 文件并删除实际文件,但这对我来说完全错误。

我知道在 python 中你在 imaplib 中有类似 UIDNEXT 的东西,但这是假设我已经登录但我没有登录。

更新:

有了这个,我可以获取下一个 uid,但我必须登录。如何在不登录的情况下获取 UIDNEXT?顺便说一句,我将 postfix/dovecot 与 mysql 一起使用。

import getpass, sys
from imapclient import IMAPClient

try:
    hostname, username = sys.argv[1:]
except ValueError:
    print 'usage %s hostname username' % sys.argv[0]

c = IMAPClient(hostname, ssl=True)

try:
    c.login(username, getpass.getpass())
except c.Error, e:
    print "Could not login in:", e
    sys.exit(1)

else:
    select_dict = c.select_folder('INBOX', readonly=True)
    for k, v in select_dict.items():
        if k == 'UIDNEXT':
            print '%s: %r' % (k,v)
    c.logout()

新更新

dovecot-uidlist 示例

16762 W105493 S104093 :1417408077.2609_1.zumance
16763 S18340 W18608 :1417429204.3464_1.zumance

获取 dovecot-uidlist uid 最后一行的代码:

l = open("dovecot-uidlist").readlines()
print l[-1].split(" ")[0]

这是邮件管道的完整脚本:

import sys
import email
import re
from DB import *
full_msg = sys.stdin.readlines()
j =  ''.join(full_msg)

msg = email.message_from_string(j)
match = re.search(r'[\w\.-]+@[\w\.-]+', msg['to'])

address = match.group(0)
address = address.split("@")

with open("/var/vmail/"+address[1]+"/"+address[0]+"/dovecot-uidlist", 'r') as f:
  first_line = f.readline()
  nextuid = first_line.split(" ")
  nextuid = re.findall(r'\d+', nextuid[2])

sql = '''INSERT INTO Email(Id, Message, Uid, Domain, Mbox) VALUES (NULL, %s, %s, %s, %s)'''
db = DB()
db.query(sql, (msg, nextuid[0], address[1], address[0],  ))

带有文件的博客文章https://pregmatch.org/read/python-procmail

4

2 回答 2

3

Dovecot 维护文件中 UID 和文件名之间的映射dovecot-uidlist。该文件首先包含一个标题行,然后每条消息包含一行。

标题行如下所示:

1 1173189136 20221

第一个数字是版本,第二个是 IMAP UIDVALIDITY,最后一个是将要使用的下一个 UID。

之后,每条消息都有自己的行,如下所示:

20220 1035478339.27041_118.example.org:2,S

第一个词是 UID,下一个是文件名。

dovecot wiki上有更多信息。

于 2014-12-01T13:10:21.903 回答
0

由于解析 dovecot-uidlist 将不起作用,因为在您使用电子邮件客户端检查电子邮件之前不会更新列表,因此我决定使用其他解决方案。该解决方案是 dovecot pre-auth 机制。在我的 python procmail 管道脚本中,我决定这样做:

import subprocess
p = subprocess.Popen( "/usr/libexec/dovecot/imap -u "+user, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)
p.stdin.write("b select INBOX\n")
p.stdin.write("e logout\n")
(stdoutdata, stderrdata) = p.communicate()
print stdoutdata

print stderrdata

stdoutdata 给我的输出看起来像这样:

* PREAUTH [CAPABILITY IMAP4rev1 LITERAL+ SASL-IR LOGIN-REFERRALS ID ENABLE IDLE SORT SORT=DISPLAY THREAD=REFERENCES THREAD=REFS THREAD=ORDEREDSUBJECT MULTIAPPEND URL-PARTIAL CATENATE UNSELECT CHILDREN NAMESPACE UIDPLUS LIST-EXTENDED I18NLEVEL=1 CONDSTORE QRESYNC ESEARCH ESORT SEARCHRES WITHIN CONTEXT=SEARCH LIST-STATUS SPECIAL-USE BINARY MOVE] Logged in as nikola@pregmatch.org
* FLAGS (\Answered \Flagged \Deleted \Seen \Draft $NotJunk NotJunk $Forwarded)
* OK [PERMANENTFLAGS (\Answered \Flagged \Deleted \Seen \Draft $NotJunk NotJunk $Forwarded \*)] Flags permitted.
* 5574 EXISTS
* 0 RECENT
* OK [UIDVALIDITY 1412448500] UIDs valid
* OK [UIDNEXT 16875] Predicted next UID
* OK [HIGHESTMODSEQ 3051] Highest
b OK [READ-WRITE] Select completed (0.009 secs).
* BYE Logging out
e OK Logout completed.

现在我要做的就是解析输出的这一部分:

* OK [UIDVALIDITY 1412448500] UIDs valid
* OK [UIDNEXT 16875] Predicted next UID

这个预授权解决了我的问题。我将在今天晚些时候(以及在我的博客上)发布带有解析部分的完整解决方案。

解决方案:

import subprocess
pSub = subprocess.Popen( "/usr/libexec/dovecot/imap -u "+username+"@"+domain_parsed, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)
pSub.stdin.write("b select INBOX\n")
pSub.stdin.write("e logout\n")
(stdoutdata, stderrdata) = pSub.communicate()
dovecotStream = open("/var/www/domain.com/scripts/server/dovecot","w")
dovecotStream.write(stdoutdata)
dovecotStream.close()


nextuidNo = []
with open("/var/www/domain.com/scripts/server/dovecot") as dovecotFile:
    dovecotFilelines = dovecotFile.read()
for dovecotFileline in dovecotFilelines.split('\n'):
    matchCheck = re.findall(r'\[UIDNEXT.+\]', dovecotFileline)
        if len(matchCheck):
            nextuidNo = re.findall(r'\d+', matchCheck[0])

print nextuidNo #this is list

完整的博客文章位于:https ://pregmatch.org/read/dovecot-preauth-python

于 2014-12-04T14:51:57.430 回答