Feature: Add option to only allow SMTP recipients matching a regular expression (disable open-relay behaviour #219)

This commit is contained in:
Ralph Slooten
2024-01-03 12:06:36 +13:00
parent aad15945b3
commit cdab59b295
6 changed files with 80 additions and 40 deletions

View File

@@ -28,7 +28,7 @@ func mailHandler(origin net.Addr, from string, to []string, data []byte) error {
msg, err := mail.ReadMessage(bytes.NewReader(data))
if err != nil {
logger.Log().Errorf("[smtpd] error parsing message: %s", err.Error())
stats.LogSMTPError()
stats.LogSMTPRejected()
return err
}
@@ -121,11 +121,10 @@ func mailHandler(origin net.Addr, from string, to []string, data []byte) error {
_, err = storage.Store(&data)
if err != nil {
logger.Log().Errorf("[db] error storing message: %s", err.Error())
stats.LogSMTPError()
return err
}
stats.LogSMTPReceived(len(data))
stats.LogSMTPAccepted(len(data))
data = nil // avoid memory leaks
@@ -153,6 +152,22 @@ func authHandlerAny(remoteAddr net.Addr, mechanism string, username []byte, _ []
return true, nil
}
// HandlerRcpt used to optionally restrict recipients based on `--smtp-allowed-recipients`
func handlerRcpt(remoteAddr net.Addr, from string, to string) bool {
if config.SMTPAllowedRecipientsRegexp == nil {
return true
}
result := config.SMTPAllowedRecipientsRegexp.MatchString(to)
if !result {
logger.Log().Warnf("[smtpd] rejected message to %s from %s (%s)", to, from, cleanIP(remoteAddr))
stats.LogSMTPRejected()
}
return result
}
// Listen starts the SMTPD server
func Listen() error {
if config.SMTPAuthAllowInsecure {
@@ -178,6 +193,7 @@ func listenAndServe(addr string, handler smtpd.Handler, authHandler smtpd.AuthHa
srv := &smtpd.Server{
Addr: addr,
Handler: handler,
HandlerRcpt: handlerRcpt,
Appname: "Mailpit",
Hostname: "",
AuthHandler: nil,

View File

@@ -240,19 +240,23 @@ export default {
</tr>
<tr>
<td>
SMTP messages received
SMTP messages accepted
</td>
<td>
{{ formatNumber(mailbox.appInfo.RuntimeStats.SMTPReceived) }}
({{ getFileSize(mailbox.appInfo.RuntimeStats.SMTPReceivedSize) }})
{{ formatNumber(mailbox.appInfo.RuntimeStats.SMTPAccepted) }}
<small class="text-secondary">
({{
getFileSize(mailbox.appInfo.RuntimeStats.SMTPAcceptedSize)
}})
</small>
</td>
</tr>
<tr>
<td>
SMTP errors
SMTP messages rejected
</td>
<td>
{{ formatNumber(mailbox.appInfo.RuntimeStats.SMTPErrors) }}
{{ formatNumber(mailbox.appInfo.RuntimeStats.SMTPRejected) }}
</td>
</tr>
<tr>

View File

@@ -762,23 +762,23 @@
"type": "integer",
"format": "int64"
},
"SMTPErrors": {
"description": "SMTP errors since run",
"SMTPAccepted": {
"description": "SMTP accepted messages since run",
"type": "integer",
"format": "int64"
},
"SMTPAcceptedSize": {
"description": "Total size in bytes of accepted messages since run",
"type": "integer",
"format": "int64"
},
"SMTPIgnored": {
"description": "SMTP messages ignored since run (duplicate IDs)",
"description": "SMTP ignored messages since run (duplicate IDs)",
"type": "integer",
"format": "int64"
},
"SMTPReceived": {
"description": "SMTP messages received via since run",
"type": "integer",
"format": "int64"
},
"SMTPReceivedSize": {
"description": "Total size in bytes of received messages since run",
"SMTPRejected": {
"description": "SMTP rejected messages since run",
"type": "integer",
"format": "int64"
},