golang实现DKIM电子邮件签名与验证插件库go-dkim的使用
golang实现DKIM电子邮件签名与验证插件库go-dkim的使用
go-dkim简介
go-dkim是一个用于Golang的DKIM(DomainKeys Identified Mail)包,可以实现电子邮件的签名和验证功能。
安装
go get github.com/toorop/go-dkim
注意:需要使用Go 1.4.2-master或1.4.3版本。
签名电子邮件
以下是一个完整的示例,展示如何使用go-dkim对电子邮件进行签名:
import (
dkim "github.com/toorop/go-dkim"
)
func main(){
// email是要签名的邮件内容(字节切片)
// privateKey是私钥(PEM编码的字节切片)
options := dkim.NewSigOptions()
options.PrivateKey = privateKey
options.Domain = "mydomain.tld" // 你的域名
options.Selector = "myselector" // DKIM选择器
options.SignatureExpireIn = 3600 // 签名过期时间(秒)
options.BodyLength = 50 // 签名包含的邮件体长度
options.Headers = []string{"from", "date", "mime-version", "received", "received"} // 要签名的邮件头
options.AddSignatureTimestamp = true // 添加签名时间戳
options.Canonicalization = "relaxed/relaxed" // 规范化方法
err := dkim.Sign(&email, options)
// 处理错误...
// 现在'email'已经被签名了!
}
验证签名
以下示例展示如何验证带有DKIM签名的电子邮件:
import (
dkim "github.com/toorop/go-dkim"
)
func main(){
// email是要验证的邮件内容(字节切片)
status, err := dkim.Verify(&email)
// 处理status和err(参见godoc了解status含义)
}
待办事项
- 处理z标签(用于诊断用途的复制头字段)
这个库提供了简单易用的接口来实现电子邮件的DKIM签名和验证功能,可以帮助开发者确保邮件的真实性和完整性。
更多关于golang实现DKIM电子邮件签名与验证插件库go-dkim的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
1 回复
更多关于golang实现DKIM电子邮件签名与验证插件库go-dkim的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
使用go-dkim实现DKIM电子邮件签名与验证
DKIM(DomainKeys Identified Mail)是一种电子邮件验证技术,允许接收方验证邮件确实来自声称的发件人域。下面我将介绍如何使用go-dkim库在Golang中实现DKIM签名和验证。
安装go-dkim
首先安装go-dkim库:
go get github.com/emersion/go-dkim
DKIM签名实现
以下是一个完整的DKIM签名示例:
package main
import (
"bytes"
"fmt"
"io"
"log"
"net/mail"
"os"
"strings"
"time"
"github.com/emersion/go-dkim"
"github.com/emersion/go-message/mail"
)
func main() {
// 示例邮件内容
rawEmail := `From: sender@example.com
To: recipient@example.com
Subject: Test DKIM Signed Email
Date: Mon, 23 Jun 2023 10:00:00 +0800
Message-ID: <123456789@example.com>
MIME-Version: 1.0
Content-Type: text/plain; charset="UTF-8"
This is a test email with DKIM signature.`
// 解析邮件
msg, err := mail.ReadMessage(strings.NewReader(rawEmail))
if err != nil {
log.Fatal(err)
}
// 创建DKIM签名选项
options := &dkim.SignOptions{
Domain: "example.com", // 你的域名
Selector: "default", // DKIM选择器
Signer: loadPrivateKey(), // 加载私钥函数
HeaderKeys: []string{ // 需要签名的头部字段
"From",
"To",
"Subject",
"Date",
"Message-ID",
"MIME-Version",
"Content-Type",
},
}
// 签名邮件
var b bytes.Buffer
if err := dkim.Sign(&b, msg, options); err != nil {
log.Fatal(err)
}
// 输出签名后的邮件
signedEmail := b.String()
fmt.Println(signedEmail)
}
// 加载私钥 - 实际应用中应从安全存储中获取
func loadPrivateKey() crypto.Signer {
// 示例私钥 - 实际应用中不应硬编码
privateKey := `-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAz6j7...` // 这里应该是你的实际私钥
block, _ := pem.Decode([]byte(privateKey))
if block == nil {
log.Fatal("failed to decode PEM block containing private key")
}
key, err := x509.ParsePKCS1PrivateKey(block.Bytes)
if err != nil {
log.Fatal(err)
}
return key
}
DKIM验证实现
以下是验证DKIM签名的代码:
package main
import (
"bytes"
"fmt"
"log"
"strings"
"github.com/emersion/go-dkim"
"github.com/emersion/go-message/mail"
)
func main() {
// 假设这是收到的已签名邮件
signedEmail := `DKIM-Signature: v=1; a=rsa-sha256; d=example.com; s=default;
c=relaxed/relaxed; q=dns/txt; t=1624411200; h=From:To:Subject:Date:
Message-ID:MIME-Version:Content-Type; bh=2jUSOH9NhtVGCQWNd9...;
b=Ofjy3U3FQTDtg/4yJ1AK0XkDeoy0...
From: sender@example.com
To: recipient@example.com
Subject: Test DKIM Signed Email
Date: Mon, 23 Jun 2023 10:00:00 +0800
Message-ID: <123456789@example.com>
MIME-Version: 1.0
Content-Type: text/plain; charset="UTF-8"
This is a test email with DKIM signature.`
// 解析邮件
msg, err := mail.ReadMessage(strings.NewReader(signedEmail))
if err != nil {
log.Fatal(err)
}
// 创建验证器
verifier := &dkim.Verifier{
LookupTXT: lookupDKIMRecord, // 自定义DNS查询函数
}
// 验证邮件
if err := verifier.Verify(msg); err != nil {
log.Fatal("DKIM verification failed:", err)
}
fmt.Println("DKIM verification succeeded!")
}
// 自定义DNS查询函数
func lookupDKIMRecord(domain string) ([]string, error) {
// 实际应用中应该执行真正的DNS查询
// 这里只是示例,返回硬编码的DKIM公钥记录
if domain == "default._domainkey.example.com" {
return []string{
"v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAz6j7...",
}, nil
}
return nil, fmt.Errorf("no DKIM record found for %s", domain)
}
实际应用建议
-
私钥管理:
- 永远不要将私钥硬编码在代码中
- 使用安全的密钥存储方案,如KMS、HashiCorp Vault等
- 考虑定期轮换密钥
-
DNS配置:
- 确保正确设置DKIM DNS记录
- 记录格式通常为:
selector._domainkey.yourdomain.com
-
签名策略:
- 选择适当的签名算法(推荐rsa-sha256)
- 确定需要签名的头部字段(From字段必须包含)
- 考虑签名过期时间
-
验证处理:
- 对于验证失败的邮件,可以记录日志或采取适当措施
- 考虑将验证结果添加到邮件头中供后续处理
性能考虑
当处理大量邮件时:
- 可以重用DKIM签名器和验证器实例
- 考虑缓存DNS查询结果
- 对于高负载系统,可能需要实现并发处理
go-dkim库提供了灵活的接口,可以集成到各种邮件处理流程中,无论是作为邮件服务器的一部分,还是作为独立的邮件处理工具。