+ if (sender_address == NULL)
+ {
+ if (f.smtp_in_pipelining_advertised && last_was_rej_mail)
+ {
+ smtp_printf("503 sender not yet given\r\n", FALSE);
+ was_rej_mail = TRUE;
+ }
+ else
+ {
+ done = synprot_error(L_smtp_protocol_error, 503, NULL,
+ US"sender not yet given");
+ was_rcpt = FALSE; /* Not a valid RCPT */
+ }
+ rcpt_fail_count++;
+ break;
+ }
+
+ /* Check for an operand */
+
+ if (smtp_cmd_data[0] == 0)
+ {
+ done = synprot_error(L_smtp_syntax_error, 501, NULL,
+ US"RCPT must have an address operand");
+ rcpt_fail_count++;
+ break;
+ }
+
+ /* Set the DSN flags orcpt and dsn_flags from the session*/
+ orcpt = NULL;
+ dsn_flags = 0;
+
+ if (fl.esmtp) for(;;)
+ {
+ uschar *name, *value;
+
+ if (!extract_option(&name, &value))
+ break;
+
+ if (fl.dsn_advertised && strcmpic(name, US"ORCPT") == 0)
+ {
+ /* Check whether orcpt has been already set */
+ if (orcpt)
+ {
+ done = synprot_error(L_smtp_syntax_error, 501, NULL,
+ US"ORCPT can be specified once only");
+ goto COMMAND_LOOP;
+ }
+ orcpt = string_copy(value);
+ DEBUG(D_receive) debug_printf("DSN orcpt: %s\n", orcpt);
+ }
+
+ else if (fl.dsn_advertised && strcmpic(name, US"NOTIFY") == 0)
+ {
+ /* Check if the notify flags have been already set */
+ if (dsn_flags > 0)
+ {
+ done = synprot_error(L_smtp_syntax_error, 501, NULL,
+ US"NOTIFY can be specified once only");
+ goto COMMAND_LOOP;
+ }
+ if (strcmpic(value, US"NEVER") == 0)
+ dsn_flags |= rf_notify_never;
+ else
+ {
+ uschar *p = value;
+ while (*p != 0)
+ {
+ uschar *pp = p;
+ while (*pp != 0 && *pp != ',') pp++;
+ if (*pp == ',') *pp++ = 0;
+ if (strcmpic(p, US"SUCCESS") == 0)
+ {
+ DEBUG(D_receive) debug_printf("DSN: Setting notify success\n");
+ dsn_flags |= rf_notify_success;
+ }
+ else if (strcmpic(p, US"FAILURE") == 0)
+ {
+ DEBUG(D_receive) debug_printf("DSN: Setting notify failure\n");
+ dsn_flags |= rf_notify_failure;
+ }
+ else if (strcmpic(p, US"DELAY") == 0)
+ {
+ DEBUG(D_receive) debug_printf("DSN: Setting notify delay\n");
+ dsn_flags |= rf_notify_delay;
+ }
+ else
+ {
+ /* Catch any strange values */
+ done = synprot_error(L_smtp_syntax_error, 501, NULL,
+ US"Invalid value for NOTIFY parameter");
+ goto COMMAND_LOOP;
+ }
+ p = pp;
+ }
+ DEBUG(D_receive) debug_printf("DSN Flags: %x\n", dsn_flags);
+ }
+ }
+
+ /* Unknown option. Stick back the terminator characters and break
+ the loop. An error for a malformed address will occur. */
+
+ else
+ {
+ DEBUG(D_receive) debug_printf("Invalid RCPT option: %s : %s\n", name, value);
+ name[-1] = ' ';
+ value[-1] = '=';
+ break;
+ }
+ }
+
+ /* Apply SMTP rewriting then extract the working address. Don't allow "<>"
+ as a recipient address */
+
+ recipient = rewrite_existflags & rewrite_smtp
+ ? rewrite_one(smtp_cmd_data, rewrite_smtp, NULL, FALSE, US"",
+ global_rewrite_rules)
+ : smtp_cmd_data;
+
+ if (!(recipient = parse_extract_address(recipient, &errmess, &start, &end,
+ &recipient_domain, FALSE)))
+ {
+ done = synprot_error(L_smtp_syntax_error, 501, smtp_cmd_data, errmess);
+ rcpt_fail_count++;
+ break;
+ }
+
+ /* If the recipient address is unqualified, reject it, unless this is a
+ locally generated message. However, unqualified addresses are permitted
+ from a configured list of hosts and nets - typically when behaving as
+ MUAs rather than MTAs. Sad that SMTP is used for both types of traffic,
+ really. The flag is set at the start of the SMTP connection.
+
+ RFC 1123 talks about supporting "the reserved mailbox postmaster"; I always
+ assumed this meant "reserved local part", but the revision of RFC 821 and
+ friends now makes it absolutely clear that it means *mailbox*. Consequently
+ we must always qualify this address, regardless. */
+
+ if (!recipient_domain)
+ if (!(recipient_domain = qualify_recipient(&recipient, smtp_cmd_data,
+ US"recipient")))
+ {
+ rcpt_fail_count++;
+ break;
+ }
+
+ /* Check maximum allowed */
+
+ if (rcpt_count > recipients_max && recipients_max > 0)
+ {
+ if (recipients_max_reject)
+ {
+ rcpt_fail_count++;
+ smtp_printf("552 too many recipients\r\n", FALSE);
+ if (!toomany)
+ log_write(0, LOG_MAIN|LOG_REJECT, "too many recipients: message "
+ "rejected: sender=<%s> %s", sender_address, host_and_ident(TRUE));
+ }
+ else
+ {
+ rcpt_defer_count++;
+ smtp_printf("452 too many recipients\r\n", FALSE);
+ if (!toomany)
+ log_write(0, LOG_MAIN|LOG_REJECT, "too many recipients: excess "
+ "temporarily rejected: sender=<%s> %s", sender_address,
+ host_and_ident(TRUE));
+ }
+
+ toomany = TRUE;
+ break;
+ }
+
+ /* If we have passed the threshold for rate limiting, apply the current
+ delay, and update it for next time, provided this is a limited host. */
+
+ if (rcpt_count > smtp_rlr_threshold &&
+ verify_check_host(&smtp_ratelimit_hosts) == OK)
+ {
+ DEBUG(D_receive) debug_printf("rate limit RCPT: delay %.3g sec\n",
+ smtp_delay_rcpt/1000.0);
+ millisleep((int)smtp_delay_rcpt);
+ smtp_delay_rcpt *= smtp_rlr_factor;
+ if (smtp_delay_rcpt > (double)smtp_rlr_limit)
+ smtp_delay_rcpt = (double)smtp_rlr_limit;
+ }
+
+ /* If the MAIL ACL discarded all the recipients, we bypass ACL checking
+ for them. Otherwise, check the access control list for this recipient. As
+ there may be a delay in this, re-check for a synchronization error
+ afterwards, unless pipelining was advertised. */
+
+ if (f.recipients_discarded)
+ rc = DISCARD;
+ else
+ if ( (rc = acl_check(ACL_WHERE_RCPT, recipient, acl_smtp_rcpt, &user_msg,
+ &log_msg)) == OK
+ && !f.smtp_in_pipelining_advertised && !check_sync())
+ goto SYNC_FAILURE;
+
+ /* The ACL was happy */
+
+ if (rc == OK)
+ {
+ BOOL more = pipeline_response();
+
+ if (user_msg)
+ smtp_user_msg(US"250", user_msg);
+ else
+ smtp_printf("250 Accepted\r\n", more);
+ receive_add_recipient(recipient, -1);
+
+ /* Set the dsn flags in the recipients_list */
+ recipients_list[recipients_count-1].orcpt = orcpt;
+ recipients_list[recipients_count-1].dsn_flags = dsn_flags;
+
+ /* DEBUG(D_receive) debug_printf("DSN: orcpt: %s flags: %d\n",
+ recipients_list[recipients_count-1].orcpt,
+ recipients_list[recipients_count-1].dsn_flags); */
+ }
+
+ /* The recipient was discarded */
+
+ else if (rc == DISCARD)
+ {
+ if (user_msg)
+ smtp_user_msg(US"250", user_msg);
+ else
+ smtp_printf("250 Accepted\r\n", FALSE);
+ rcpt_fail_count++;
+ discarded = TRUE;
+ log_write(0, LOG_MAIN|LOG_REJECT, "%s F=<%s> RCPT %s: "
+ "discarded by %s ACL%s%s", host_and_ident(TRUE),
+ sender_address_unrewritten ? sender_address_unrewritten : sender_address,
+ smtp_cmd_argument, f.recipients_discarded ? "MAIL" : "RCPT",
+ log_msg ? US": " : US"", log_msg ? log_msg : US"");
+ }
+
+ /* Either the ACL failed the address, or it was deferred. */