| 197 | } |
| 198 | |
| 199 | func (dd *msgpipelineDelivery) srcBlockForAddr(ctx context.Context, mailFrom string) (sourceBlock, error) { |
| 200 | cleanFrom := mailFrom |
| 201 | if mailFrom != "" { |
| 202 | var err error |
| 203 | cleanFrom, err = address.ForLookup(mailFrom) |
| 204 | if err != nil { |
| 205 | return sourceBlock{}, &exterrors.SMTPError{ |
| 206 | Code: 501, |
| 207 | EnhancedCode: exterrors.EnhancedCode{5, 1, 7}, |
| 208 | Message: "Unable to normalize the sender address", |
| 209 | Err: err, |
| 210 | } |
| 211 | } |
| 212 | } |
| 213 | |
| 214 | for _, srcIn := range dd.d.sourceIn { |
| 215 | _, ok, err := srcIn.t.Lookup(ctx, cleanFrom) |
| 216 | if err != nil { |
| 217 | dd.log.Error("source_in lookup failed", err, "key", cleanFrom) |
| 218 | continue |
| 219 | } |
| 220 | if !ok { |
| 221 | continue |
| 222 | } |
| 223 | return srcIn.block, nil |
| 224 | } |
| 225 | |
| 226 | // First try to match against complete address. |
| 227 | srcBlock, ok := dd.d.perSource[cleanFrom] |
| 228 | if !ok { |
| 229 | // Then try domain-only. |
| 230 | _, domain, err := address.Split(cleanFrom) |
| 231 | // mailFrom != "" is added as a special condition |
| 232 | // instead of extending address.Split because "" |
| 233 | // is not a valid RFC 282 address and only a special |
| 234 | // value for SMTP. |
| 235 | if err != nil && cleanFrom != "" { |
| 236 | return sourceBlock{}, &exterrors.SMTPError{ |
| 237 | Code: 501, |
| 238 | EnhancedCode: exterrors.EnhancedCode{5, 1, 3}, |
| 239 | Message: "Invalid sender address", |
| 240 | Err: err, |
| 241 | Reason: "Can't extract local-part and host-part", |
| 242 | } |
| 243 | } |
| 244 | |
| 245 | // domain is already case-folded and normalized by the message source. |
| 246 | srcBlock, ok = dd.d.perSource[domain] |
| 247 | if !ok { |
| 248 | // Fallback to the default source block. |
| 249 | srcBlock = dd.d.defaultSource |
| 250 | dd.log.Debugf("sender %s matched by default rule", mailFrom) |
| 251 | } else { |
| 252 | dd.log.Debugf("sender %s matched by domain rule '%s'", mailFrom, domain) |
| 253 | } |
| 254 | } else { |
| 255 | dd.log.Debugf("sender %s matched by address rule '%s'", mailFrom, cleanFrom) |
| 256 | } |