162 lines
3.1 KiB
Go
162 lines
3.1 KiB
Go
package rspamc
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"net/http"
|
|
"strconv"
|
|
|
|
json "github.com/json-iterator/go"
|
|
|
|
"git.vsu.ru/ai/rspamd-cgp/cgp"
|
|
"git.vsu.ru/ai/rspamd-cgp/config"
|
|
)
|
|
|
|
var (
|
|
headerJunkG string = "X-Junk-Score: [XX]"
|
|
headerJunkA string = "X-Junk-Score: [XXXX]"
|
|
headerJunkR string = "X-Junk-Score: [XXXXXXXXXX]"
|
|
)
|
|
|
|
var authservId string
|
|
var client *http.Client
|
|
var discard bool
|
|
var host string
|
|
|
|
func init() {
|
|
|
|
config := config.New()
|
|
|
|
if config.AuthservId != "" {
|
|
authservId = config.AuthservId
|
|
} else {
|
|
authservId = cgp.MainDomain
|
|
}
|
|
|
|
discard = config.Discard
|
|
host = "http://" + config.Host + "/checkv2"
|
|
|
|
tr := &http.Transport{
|
|
DisableCompression: true,
|
|
}
|
|
|
|
client = &http.Client{
|
|
Timeout: config.Timeout,
|
|
Transport: tr,
|
|
}
|
|
}
|
|
|
|
func appendHeaders(hdrs, junk *string) *string {
|
|
if *hdrs != "" {
|
|
headers := *hdrs + "\n" + *junk
|
|
return &headers
|
|
} else {
|
|
return junk
|
|
}
|
|
}
|
|
|
|
func Scan(seq int, filename string) {
|
|
|
|
from, rcpts, auth, ip, qid, body, err := cgp.Message(&filename)
|
|
if err != nil {
|
|
cgp.Failure(seq, qid, err)
|
|
return
|
|
}
|
|
|
|
req, err := http.NewRequest("POST", host, bytes.NewReader(body))
|
|
if err != nil {
|
|
cgp.Failure(seq, qid, err)
|
|
return
|
|
}
|
|
|
|
req.Header.Add("MTA-Tag", authservId)
|
|
req.Header.Add("User-Agent", "rspamd-cgp")
|
|
req.Header.Add("From", from)
|
|
req.Header.Add("Queue-ID", strconv.Itoa(qid))
|
|
if len(auth) > 0 {
|
|
req.Header.Add("User", auth)
|
|
}
|
|
if len(ip) > 0 {
|
|
req.Header.Add("IP", ip)
|
|
}
|
|
for _, rcpt := range rcpts {
|
|
req.Header.Add("Rcpt", rcpt)
|
|
}
|
|
|
|
resp, err := client.Do(req)
|
|
if err != nil {
|
|
cgp.Failure(seq, qid, err)
|
|
return
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
rbody, err := ioutil.ReadAll(resp.Body)
|
|
if err != nil {
|
|
cgp.Failure(seq, qid, err)
|
|
return
|
|
}
|
|
|
|
var js map[string]interface{}
|
|
if err := json.Unmarshal(rbody, &js); err != nil {
|
|
cgp.Failure(seq, qid, err)
|
|
return
|
|
}
|
|
|
|
var headers string
|
|
|
|
if _, ok := js["dkim-signature"]; ok {
|
|
headers = "DKIM-Signature: " + js["dkim-signature"].(string)
|
|
}
|
|
|
|
if milter, ok := js["milter"]; ok {
|
|
if hdrs, ok := milter.(map[string]interface{})["add_headers"]; ok {
|
|
for h, vh := range hdrs.(map[string]interface{}) {
|
|
if v, ok := vh.(map[string]interface{})["value"].(string); ok && v != "" {
|
|
if headers != "" {
|
|
headers += "\n" + h + ": " + v
|
|
} else {
|
|
headers = h + ": " + v
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
action := js["action"]
|
|
|
|
cgp.Putline("* %d [%d]: Action: %s; Score: %.2f/%.2f; Time elapsed: %.3fs\n",
|
|
seq, qid, action, js["score"], js["required_score"], js["time_real"])
|
|
|
|
switch action {
|
|
case "no action":
|
|
if headers != "" {
|
|
cgp.AddHeader(seq, cgp.ReplaceSpecChars(&headers))
|
|
} else {
|
|
cgp.Ok(seq)
|
|
}
|
|
|
|
case "reject":
|
|
if discard {
|
|
cgp.Discard(seq)
|
|
} else {
|
|
cgp.AddHeader(seq, cgp.ReplaceSpecChars(appendHeaders(&headers, &headerJunkR)))
|
|
}
|
|
|
|
case "rewrite subject":
|
|
fallthrough
|
|
case "add header":
|
|
cgp.AddHeader(seq, cgp.ReplaceSpecChars(appendHeaders(&headers, &headerJunkA)))
|
|
|
|
case "greylist":
|
|
cgp.AddHeader(seq, cgp.ReplaceSpecChars(appendHeaders(&headers, &headerJunkG)))
|
|
|
|
case "soft reject":
|
|
cgp.Reject(seq)
|
|
|
|
default:
|
|
cgp.Failure(seq, qid, fmt.Errorf("Unknown action: %v", action))
|
|
}
|
|
|
|
}
|