在浏览/使用这个伟大网站上的解决方案一段时间后,我终于可以参与其中了。
我对自己想要的东西有一个非常明确的概念,但我正在寻找最好的方式去那里。
我想要什么?:
一段时间以来,我在raspberry-pi上使用电子邮件服务器设置,到目前为止效果很好。 它由一个dovecot服务器和一些筛选过滤器组成,用于将我的许多电子邮件地址分类到单独的收件箱子目录中。 还有一个垃圾邮件过滤器,每晚通过脚本讲授火腿和垃圾邮件之间的区别。 (基本上他被告知垃圾邮件在垃圾文件夹中,而其他每个文件夹都包含火腿)
我想将此行为复制到专用的“Newsletter”文件夹中。 此文件夹不包含需要立即查看或报告的紧急消息。
计划是手动将电子邮件放入“新闻”文件夹,并让脚本每天扫描一次此文件夹。如果它从没有筛选规则的地址中找到一封电子邮件,则应该创建一条规则,以便在到达时自动将来自此地址的邮件放入“新闻”文件夹中。
实现的步骤?:
为此,脚本需要扫描现有的.dovecot.sieve文件, 从“新闻文件夹”规则中提取地址到单独的文件 或比较对象。
/*Example of a sieve filter:*/
require "fileinto";
/* Global Spam Filter */
if anyof (header :contains "subject" "*SPAM*",
header :contains "X-Spam-Flag" "YES" ) {
fileinto "Junk";
stop;
}
/* LAN Emails Filter */
elsif address :is "to" "lan@docbrown.pi" {
fileinto "INBOX.Lokal";
stop;
}
/* Newsletter Filter */
elsif anyof (address :is "from" "newsletter@example.com",
address :is "from" "news@yahoo.de",
address :is "from" "info@mailbox.de",
address :is "from" "something@somewhere.de") {
fileinto "INBOX.Newsletter";
stop;
}
/* gmail Account Filter */
elsif address :is "to" "docbrown@gmail.com" {
fileinto "INBOX.gmail";
stop;
}
/* Yahoo Account Filter */
elsif address :is "to" "docbrown@yahoo.de" {
fileinto "INBOX.yahoo";
stop;
}
else {
# The rest goes into INBOX
# default is "implicit keep", we do it explicitly here
keep;
}
然后需要处理所有电子邮件 “新闻”文件夹的maildir目录并在电子邮件中搜索 对于“发件人:”字段和尖括号中的电子邮件地址
Date: Mon, 4 Nov 2013 16:38:30 +0100 (CET)
From: Johannes Ebert - Redaktion c't <infoservice@heise.de>
To: docbrown@example.de
将它们与筛选文件中提取的地址进行比较,如果地址没有过滤规则
(例如,在列表中找不到)为其创建一个(或者只是将其添加到提取的地址)
到目前为止的进展:
我试图通过简单地使用bash命令和实用程序来实现这一点。 这让我接近了几乎可以从dovecot.sieve文件中提取电子邮件地址的地方,但这对我来说非常复杂并需要一些时间。
#!/bin/sh
cp /home/mailman/.dovecot.sieve /home/mailman/autosieve/dovecot.sieve_`date +backup_%d%m%Y`
#echo "" > search.txt
X=grep -n "Newsletter Filter" /home/mailman/.dovecot.sieve #get rule start line number, some magic needs to happen here to just apply the numbers and not the full output by grep
Y=grep -n "INBOX.Newsletter" /home/mailman/.dovecot.sieve #get rule end line number
$X++ #increment to go into the next line
$Y-- #decrement to go into the previous line
sed -n ‘$X,$Yp’ /home/mailman/.dovecot.sieve > /home/mailman/search.txt #copy lines into separate search_file
less /home/mailman/search.txt | awk -F '"' '{ if ($2 != "") print $4 }' > /home/mailman/adressen.txt # filter addresses and export to separate file
所以我想知道我是否可以通过使用python来实现更轻松。 我在另一个覆盆子项目中修改它,但没有时间完全沉浸在python宇宙中。
所以我很乐意在这里提供一些帮助/建议/指出正确的方向。
直到现在我找到了一些类似问题的解决方案(第一部分)需要提取,但我无法完全适应它,或者由于无法执行脚本而犯了一些错误。
#!/usr/bin/python
file = open("dovecot.sieve", "r")
rule = {}
current_rule = None
for line in file:
line = line.split()
if (line[2] == "INBOX.Newsletter"):
break
if (line[1] == "/* Newsletter Filter */"):
current_rule = rule.setdefault('Newsletter', [])
continue
if (line[5] == "from"):
current_rule.append(line[6])
continue
if (line[3] == "from"):
current_rule.append(line[4])
continue
file.close()
# Now print out all the data
import pprint
print "whole array"
print "=============================="
pprint.pprint(rule)
print
print "addresses found"
print "=========================="
pprint.pprint(rule['Newsletter'])
有人还可以推荐一个用于python的IDE,带有调试器等等吗? Eclipse会浮现在我的脑海中,或者还有其他什么东西(可能没那么资源饥饿)?
答案 0 :(得分:0)
好的,所以我有空余时间来征服我自己的问题。有些人正在挖掘并阅读一些代码片段并在Eclipse中使用Pydev进行测试。
现在我将这个脚本作为一个cron作业在晚上运行。
它做了什么?
它收集dovecot.sieve文件中的所有电子邮件地址(以及“简报”规则集中的电子邮件地址)。然后在INBOX.Newsletter文件夹中查找任何未注册的电子邮件地址,方法是将它们与收集的地址进行比较。 如果找到新地址,则会保存旧筛选文件的副本,然后重写现有文件。新的电子邮件地址将插入“简报”规则集中,以便将这些电子邮件重定向到指定的新闻稿文件夹。
#!/usr/bin/python2.7
import os, sys
#Get the already configured email senders...
addresses = {}
current_addresses = None
with open("/home/postman/.dovecot.sieve", "r") as sieveconf:
for line in sieveconf:
if "INBOX.Newsletter" in line:
break
if "Newsletter Filter" in line:
current_addresses = addresses.setdefault('found', [])
continue
if "from" in line and current_addresses != None:
line = line.split('"')
if (len(line) > 4) and (line[1] == "from"):
current_addresses.append(line[3])
continue
#save the count for later
addr_num = 0
addr_num = len(addresses['found'])
#iterate all files in all sub-directories of INBOX.Newsletter
for root, _,files in os.walk("/home/postman/Mails/.INBOX.Newsletter"):
#for each file in the current directory
for emaildir in files:
#open the file
with open(os.path.join(root, emaildir), "r") as mail:
#scan line by line
for line in mail:
if "From: " in line:
#arm boolean value for adding to list
found_sw = False
#extract substring from line
found = ((line.split('<'))[1].split('>')[0])
#compare found address with already existing addresses in dictionary
for m_addr in addresses['found']:
if m_addr == found:
#remember if the address is already in the dictionary
found_sw = True
break
if not found_sw:
#if the address is not included in the dictionary put it there
current_addresses.append(found)
break
# Now print out all the data
#import pprint
#print "addresses found:"
#print "=========================="
#pprint.pprint(addresses['found'])
#print
#print "orig_nmbr_of_addresses:" , addr_num
#print "found_nmbr_of_addresses:", len(addresses['found'])
#print "not_recorded_addresses:", (len(addresses['found']) - (addr_num))
#Compare if the address count has changed
if addr_num == len(addresses['found']):
#exit the script since no new addresses have been found
sys.exit
else:
#copy original sieve file for backup
import datetime
from shutil import copyfile
backupfilename = '.backup_%s.sieve'% datetime.date.today()
copyfile('dovecot.sieve', backupfilename)
#edit the existing sieve file and add the new entries
import fileinput
#open file for in place editing
for line in fileinput.input('dovecot.sieve', inplace=1):
#if the line before the last entry is reached
if addresses['found'][(addr_num - 2)] in line:
#print the line
print line,
#put new rules before the last line (just to avoid extra handling for last line, since the lines before are rather identical)
for x in range (addr_num, (len(addresses['found']))):
print ' address :is "from" "%s",'% addresses['found'][x]
else:
#print all other lines
print line,