Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 70 additions & 0 deletions eicar.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package main

import (
"fmt"
"net/smtp"
)

type eicarResult struct {
sent bool
result string
}

// eicarString assembles the EICAR test string at runtime to avoid static AV detection.
func eicarString() string {
p1 := `X5O!P%@AP[4\PZX54(P^)7CC)7}`
p2 := `$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*`
return p1 + p2
}

// sendEICAR sends the EICAR test file as an email attachment to the target mail server.
// A virus filter that detects it will reject the message; sent=true means it was accepted.
func sendEICAR(mailFrom string, mailTo string, targetHost string, targetPort string) (eicarResult, error) {
var er eicarResult

c, err := smtp.Dial(targetHost + ":" + targetPort)
if err != nil {
return er, err
}
defer c.Quit() //nolint:errcheck

if err = c.Mail(mailFrom); err != nil {
er.result = err.Error()
return er, nil
}

if err = c.Rcpt(mailTo); err != nil {
er.result = err.Error()
return er, nil
}

wc, err := c.Data()
if err != nil {
return er, err
}

body := "MIME-Version: 1.0\r\n" +
"Content-Type: multipart/mixed; boundary=\"eicartest\"\r\n" +
"Subject: EICAR AV Test\r\n" +
"From: " + mailFrom + "\r\n" +
"To: " + mailTo + "\r\n\r\n" +
"--eicartest\r\n" +
"Content-Type: application/octet-stream\r\n" +
"Content-Disposition: attachment; filename=\"eicar.com\"\r\n\r\n" +
eicarString() + "\r\n" +
"--eicartest--\r\n"

if _, err = fmt.Fprint(wc, body); err != nil {
er.result = err.Error()
wc.Close() //nolint:errcheck
return er, nil
}

if err = wc.Close(); err != nil {
er.result = err.Error()
return er, nil
}

er.sent = true
return er, nil
}
19 changes: 19 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,13 +58,15 @@ type mxresult struct {
smtps bool
openrelay bool
vrfysupport bool
eicardelivered bool
smugglevuln bool
smuggleresp string
smuggleerror string
}

func main() {
blacklist := flag.BoolP("blacklist", "b", false, "Check if the service is on blacklists")
eicar := flag.BoolP("eicar", "e", false, "Send EICAR test file to check AV filtering (use only on servers you are authorized to test)")
dkimSelector := flag.StringP("dkim-selector", "S", "",
"The DKIM selector. If set a DKIM check is performed on the provided service domain")
dnsServer := flag.StringP("dnsserver", "d", "8.8.8.8", "The dns server to be requested")
Expand Down Expand Up @@ -396,6 +398,23 @@ func main() {
printOK("Server is not an open relay")
}

// EICAR test
if *eicar {
printSection("EICAR AV Test")
er, err := sendEICAR(*mailFrom, *mailTo, targetHost, port)
if err != nil {
printError(err.Error())
} else if er.sent {
singlemx.eicardelivered = true
printInfo("EICAR test file", "accepted by server")
} else {
printInfo("EICAR test file", "rejected by server")
if len(er.result) > 0 {
printInfo("Response", er.result)
}
}
}

// STARTTLS test
printSection("STARTTLS")
singlemx.starttls = orresult.starttlsbool
Expand Down
Loading