在go语言中以邮件标题中获取SPF和DMARC,来判断是否为垃圾邮件之垃圾邮件过滤器功能实现

2023-06-01 00:00:00 过滤器 中以 垃圾邮件

你正在用go构建一个带有垃圾邮件过滤器的电子邮件服务器,你想查询一个域的 SPF(发送者政策框架)和 DMARC(基于域的消息验证、报告和一致性)记录。

如何获得一个域名的 SPF 和 DMARC 记录?

注意:

SPF记录是为了防止垃圾邮件发送者用伪造的发件人地址向你的域名发送邮件。

收件人或垃圾邮件过滤程序可以参考 SPF 记录,以确定声称来自你的域名的邮件是否来自授权的邮件服务器。

DMARC是一个电子邮件验证系统,旨在检测和防止电子邮件欺骗。

它建立在发件人政策框架(SPF)和域名密钥识别邮件(DKIM)的基础之上。


解决方案:

一封适当的电子邮件有标题信息,你可以用来提取该域名的SPF和DMARC记录。

在电子邮件的标题中,寻找发件人:并提取域名。

例如,对于 [email protected],我们只想要 hello.com。

用下面的代码例子查询域名。

SPF记录是一种DNS记录,显示哪些邮件服务器被允许代表一个域名发送电子邮件。

例如,sengrid.com的客户通常有:

include:sendgrid.net

在他们的SPF记录中。

这仅仅意味着sendgrid.net被授权代表客户发送电子邮件。

例如,来自testingmom.com的电子邮件在标题中的From: 部分会有sendgrid.net。


并非所有的域名在其DNS TXT中都有DMARC记录。

然而,查询该域名的DMARC也是很好的。

例如,Foursquare.com是sendgrid.com的客户,它的DNS中配置了DMARC。

v=DMARC1; p=none; rua=mailto:[email protected]

下面的代码将告诉你如何用 net.Lookup() 函数查询一个域名的 DNS 记录,

提取 SPF 和 DMARC 记录,并将 DMARC 记录转换为 map(哈希表)以便快速查询。


有了 SPF 和 DMARC 信息,你就可以配置垃圾邮件过滤器,

使其允许邮件通过、拒绝邮件或将其标记为垃圾邮件并传送到垃圾邮件箱。


代码示例:

emailheader.go

 package main
 import (
         "fmt"
         "net"
         "os"
         "strings"
 )
 func ExtractDMARC(records []string) string {
         for _, value := range records {
                 if strings.Contains(value, "v=DMARC1") {
                         return value
                 }
         }
         //默认
         return "no DMARC found"
 }
 func ExtractSPF(records []string) string {
         for _, value := range records {
                 if strings.Contains(value, "v=spf1") {
                         return value
                 }
         }
         //默认
         return "no SPF found"
 }
 func main() {
         if len(os.Args) != 2 {
                 fmt.Printf("Usage : %s <domain to query> \n", os.Args[0])
                 os.Exit(0)
         }
         domain := os.Args[1]
         fmt.Printf("Getting %s DNS records...\n", domain)
         //提取目标域的DNS记录
         dnsTXT, err := net.LookupTXT(domain)
         if err != nil {
                 fmt.Println("unable to query domain. Error : " + err.Error())
                 os.Exit(-1)
         }
         // sanity check
         for index, record := range dnsTXT {
                 fmt.Printf("[%d] : %s\n", index, record)
         }
         spf := ExtractSPF(dnsTXT)
         fmt.Printf("\n\nSPF record : %s\n", spf)
         //通过在LookupTXT查询中添加"_dmarc "来提取DMARC记录。
         // DMARC记录在DNS中以子域标签_dmarc发布。
         dmarcTXT, err := net.LookupTXT("_dmarc." + domain)
         if err != nil {
                 fmt.Println("unable to query DMARC. Error : " + err.Error())
                 os.Exit(-1)
         }
         dmarc := ExtractDMARC(dmarcTXT)
         fmt.Printf("\n\nDMARC record : %s\n", dmarc)
         //首先将DMARC名称值标签分解成片状,然后追加到地图(哈希表)中。
         dmarcSlice := strings.Fields(dmarc)
         //fmt.Println(dmarcSlice)
         //来自https://en.wikipedia.org/wiki/DMARC
         // v是版本,p是策略,sp是子域策略、
         // pct是应用该策略的 "坏 "邮件的百分比、
         // 而rua是发送汇总报告的URI。
         dmarcMap := make(map[string]interface{})
         for _, value := range dmarcSlice {
                 // break value by = sign
                 tmp := strings.Split(value, "=")
                 dmarcMap[tmp[0]] = tmp[1]
         }
         //由你来决定如何处理这些数据
         //将它们存储到数据库中
         //使用这些信息来配置垃圾邮件过滤器
         fmt.Println("DMARC version : ", dmarcMap["v"])
         fmt.Println("DMARC policy : ", dmarcMap["p"])
         fmt.Println("DMARC subdomain policy : ", dmarcMap["sp"])
         fmt.Println("DMARC bad percentage : ", dmarcMap["pct"])
         fmt.Println("DMARC send reports to : ", dmarcMap["rua"])
 }

建立并运行代码。

./emailheader sendgrid.com的输出样本:

 Getting sendgrid.com DNS records...
 [0] : loaderio=dc99536e3eb902ffc82885541e224e7c
 [1] : MS=ms77173225
 [2] : v=spf1 ip4:167.89.32.5 ip4:167.89.32.50 ip4:50.31.36.199 ip4:50.31.36.205 ip4:50.31.36.208 ip4:50.31.36.213 ip4:50.31.36.197 ip4:167.89.25.84 include:_spf.google.com include:partners.sendgrid.com include:_labs.sendgrid.com -all
 [3] : google-site-verification=ou-V2e37_e-apeuJQ4IZh8VPHGkwMHCeehxZiVJUQ_s
 SPF record : v=spf1 ip4:167.89.32.5 ip4:167.89.32.50 ip4:50.31.36.199 ip4:50.31.36.205 ip4:50.31.36.208 ip4:50.31.36.213 ip4:50.31.36.197 ip4:167.89.25.84 include:_spf.google.com include:partners.sendgrid.com include:_labs.sendgrid.com -all
 DMARC record : v=DMARC1; p=quarantine; sp=none; adkim=r; aspf=r; fo=1; pct=100; rf=afrf; ri=86400; rua=mailto:[email protected],mailto:[email protected]; ruf=mailto:[email protected],mailto:[email protected]
 [v=DMARC1; p=quarantine; sp=none; adkim=r; aspf=r; fo=1; pct=100; rf=afrf; ri=86400; rua=mailto:[email protected],mailto:[email protected]; ruf=mailto:[email protected],mailto:[email protected]]
 DMARC version :  DMARC1;
 DMARC policy :  quarantine;
 DMARC subdomain policy :  none;
 DMARC bad percentage :  100;
 DMARC send reports to :  mailto:[email protected],mailto:[email protected];

以./emailheader digitalocean.com的输出样本:

Getting digitalocean.com DNS records...
 [0] : v=spf1 ip4:167.89.16.30/32 ip4:167.89.16.245/32 ip4:167.89.16.183/32 include:servers.mcsv.net include:mailgun.org include:_spf.google.com -all
 [1] : mailru-verification: 93fb13cddf97475f
 [2] : google-site-verification=l_eZFhD-V_qPB1OYMoA4-Qg1QJT0oQm6j1Z1Dl_f65k
 [3] : globalsign-domain-verification=QCdmvx2FmvCpeqYXQsTAMJMq2YjyK0VzLosSdN6aMP
 SPF record : v=spf1 ip4:167.89.16.30/32 ip4:167.89.16.245/32 ip4:167.89.16.183/32 include:servers.mcsv.net include:mailgun.org include:_spf.google.com -all
 DMARC record : v=DMARC1; p=reject; pct=100; rua=mailto:[email protected]; ruf=mailto:[email protected]
 [v=DMARC1; p=reject; pct=100; rua=mailto:[email protected]; ruf=mailto:[email protected]]
 DMARC version :  DMARC1;
 DMARC policy :  reject;
 DMARC subdomain policy :  <nil>
 DMARC bad percentage :  100;
 DMARC send reports to :  mailto:[email protected];


相关文章