コード例 #1
0
int mail_send_forward(struct mail_deliver_context *ctx, const char *forwardto)
{
    static const char *hide_headers[] = {
        "Return-Path"
    };
    struct istream *input;
    struct ostream *output;
    struct smtp_client *smtp_client;
    const char *return_path;

    if (mail_get_stream(ctx->src_mail, NULL, NULL, &input) < 0)
	    return -1;

    return_path = mail_deliver_get_return_address(ctx);
    if (mailbox_get_settings(ctx->src_mail->box)->mail_debug) {
	    i_debug("Sending a forward to <%s> with return path <%s>",
		    forwardto, return_path);
    }

    smtp_client = smtp_client_open(ctx->set, forwardto, return_path, &output);

    input = i_stream_create_header_filter(input, HEADER_FILTER_EXCLUDE |
                                          HEADER_FILTER_NO_CR, hide_headers,
                                          N_ELEMENTS(hide_headers),
					  *null_header_filter_callback,
					  (void *)NULL);

    (void)o_stream_send_istream(output, input);
    i_stream_unref(&input);

    return smtp_client_close(smtp_client);
}
コード例 #2
0
int mail_send_rejection(struct mail_deliver_context *ctx, const char *recipient,
			const char *reason)
{
    struct mail *mail = ctx->src_mail;
    struct istream *input;
    struct smtp_client *smtp_client;
    struct ostream *output;
    const char *return_addr, *hdr;
    const char *value, *msgid, *orig_msgid, *boundary;
    string_t *str;
    int ret;

    if (mail_get_first_header(mail, "Message-ID", &orig_msgid) < 0)
	    orig_msgid = NULL;

    if (mail_get_first_header(mail, "Auto-Submitted", &value) > 0 &&
	strcasecmp(value, "no") != 0) {
	    i_info("msgid=%s: Auto-submitted message discarded: %s",
		   orig_msgid == NULL ? "" : str_sanitize(orig_msgid, 80),
		   str_sanitize(reason, 512));
	    return 0;
    }

    return_addr = mail_deliver_get_return_address(ctx);
    if (return_addr == NULL) {
	    i_info("msgid=%s: Return-Path missing, rejection reason: %s",
		   orig_msgid == NULL ? "" : str_sanitize(orig_msgid, 80),
		   str_sanitize(reason, 512));
	    return 0;
    }

    if (mailbox_get_settings(mail->box)->mail_debug) {
	    i_debug("Sending a rejection to %s: %s", recipient,
		    str_sanitize(reason, 512));
    }

    smtp_client = smtp_client_open(ctx->set, return_addr, NULL, &output);

    msgid = mail_deliver_get_new_message_id(ctx);
    boundary = t_strdup_printf("%s/%s", my_pid, ctx->set->hostname);

    str = t_str_new(512);
    str_printfa(str, "Message-ID: %s\r\n", msgid);
    str_printfa(str, "Date: %s\r\n", message_date_create(ioloop_time));
    str_printfa(str, "From: Mail Delivery Subsystem <%s>\r\n",
		ctx->set->postmaster_address);
    str_printfa(str, "To: <%s>\r\n", return_addr);
    str_append(str, "MIME-Version: 1.0\r\n");
    str_printfa(str, "Content-Type: "
		"multipart/report; report-type=%s;\r\n"
		"\tboundary=\"%s\"\r\n",
		ctx->dsn ? "delivery-status" : "disposition-notification",
		boundary);
    str_append(str, "Subject: ");
    var_expand(str, ctx->set->rejection_subject,
	       get_var_expand_table(mail, reason, recipient));
    str_append(str, "\r\n");

    str_append(str, "Auto-Submitted: auto-replied (rejected)\r\n");
    str_append(str, "Precedence: bulk\r\n");
    str_append(str, "\r\nThis is a MIME-encapsulated message\r\n\r\n");

    /* human readable status report */
    str_printfa(str, "--%s\r\n", boundary);
    str_append(str, "Content-Type: text/plain; charset=utf-8\r\n");
    str_append(str, "Content-Disposition: inline\r\n");
    str_append(str, "Content-Transfer-Encoding: 8bit\r\n\r\n");

    var_expand(str, ctx->set->rejection_reason,
	       get_var_expand_table(mail, reason, recipient));
    str_append(str, "\r\n");

    if (ctx->dsn) {
	    /* DSN status report: For LDA rejects. currently only used when
	       user is out of quota */
	    str_printfa(str, "--%s\r\n"
			"Content-Type: message/delivery-status\r\n\r\n",
			boundary);
	    str_printfa(str, "Reporting-MTA: dns; %s\r\n", ctx->set->hostname);
	    if (mail_get_first_header(mail, "Original-Recipient", &hdr) > 0)
		    str_printfa(str, "Original-Recipient: rfc822; %s\r\n", hdr);
	    str_printfa(str, "Final-Recipient: rfc822; %s\r\n", recipient);
	    str_append(str, "Action: failed\r\n");
	    str_printfa(str, "Status: %s\r\n", ctx->mailbox_full ? "5.2.2" : "5.2.0");
    } else {
	    /* MDN status report: For Sieve "reject" */
	    str_printfa(str, "--%s\r\n"
			"Content-Type: message/disposition-notification\r\n\r\n",
			boundary);
	    str_printfa(str, "Reporting-UA: %s; Dovecot Mail Delivery Agent\r\n",
			ctx->set->hostname);
	    if (mail_get_first_header(mail, "Original-Recipient", &hdr) > 0)
		    str_printfa(str, "Original-Recipient: rfc822; %s\r\n", hdr);
	    str_printfa(str, "Final-Recipient: rfc822; %s\r\n", recipient);

	    if (orig_msgid != NULL)
		    str_printfa(str, "Original-Message-ID: %s\r\n", orig_msgid);
	    str_append(str, "Disposition: "
		       "automatic-action/MDN-sent-automatically; deleted\r\n");
    }
    str_append(str, "\r\n");

    /* original message's headers */
    str_printfa(str, "--%s\r\nContent-Type: message/rfc822\r\n\r\n", boundary);
    o_stream_nsend(output, str_data(str), str_len(str));

    if (mail_get_hdr_stream(mail, NULL, &input) == 0) {
	    /* Note: If you add more headers, they need to be sorted.
	       We'll drop Content-Type because we're not including the message
	       body, and having a multipart Content-Type may confuse some
	       MIME parsers when they don't see the message boundaries. */
	    static const char *const exclude_headers[] = {
		    "Content-Type"
	    };

	    input = i_stream_create_header_filter(input,
	    		HEADER_FILTER_EXCLUDE | HEADER_FILTER_NO_CR |
			HEADER_FILTER_HIDE_BODY, exclude_headers,
			N_ELEMENTS(exclude_headers),
			*null_header_filter_callback, (void *)NULL);

	    ret = o_stream_send_istream(output, input);
	    i_stream_unref(&input);

	    i_assert(ret != 0);
    }

    str_truncate(str, 0);
    str_printfa(str, "\r\n\r\n--%s--\r\n", boundary);
    o_stream_nsend(output, str_data(str), str_len(str));
    return smtp_client_close(smtp_client);
}
コード例 #3
0
ファイル: mail.c プロジェクト: 503serviceunavailable/magma
/**
 * @brief	Send (relay) a message composed by a user via a portal session.
 * @see	smtp_relay_message() - a lot of logic borrowed from here.
 * @param	from		a pointer to a managed string containing the email address specified as the From address.
 * @param	to			a pointer to a managed string containing the destination email address of the message.
 * @param	data		a pointer to a managed string containing the raw data of the mail message.
 * @param	send_size	if greater than 0, specify the optional SIZE parameter to the MAIL FROM command.
 * @param	errmsg		the address of a pointer to a null-terminated string that will be set to a descriptive error message on failure.
 * @return	true if the mail message was sent successfully, or false otherwise.
 */
bool_t portal_smtp_relay_message(stringer_t *from, inx_t *to, stringer_t *data, size_t send_size, chr_t **errmsg) {

	inx_cursor_t *cursor;
	stringer_t *to_address;
	client_t *client;
	int_t state, nsentto = 0;

	if (!from || !to || !data || !errmsg) {
		*errmsg = "Unexpected internal failure occurred while sending message.";
		return false;
	}

	/*if (mail_add_outbound_headers(con) != 1) {
		log_pedantic("Could not add the outbound headers.");
		return false;
	}*/

	// Open the connection to the SMTP server.
	if (!(client = smtp_client_connect(0))) {
		*errmsg = "Encountered transport error with relay server.";
		return false;
	}

	// Send HELO.
	if (smtp_client_send_helo(client)!= 1) {
		*errmsg = "Handshake with relay server failed.";
		smtp_client_close(client);
		return false;
	}

	// Send MAIL FROM.
	if ((state = smtp_client_send_mailfrom(client, from, send_size)) != 1) {
		*errmsg = "Error occurred while sending From field to email server.";
		smtp_client_close(client);
		return false;
	}

	// Send the RCPT TO command.
	if (!(cursor = inx_cursor_alloc(to))) {
		*errmsg = "Internal occurred while expanding recipient list.";
		smtp_client_close(client);
		return false;
	}

	while ((to_address = inx_cursor_value_next(cursor))) {

		if ((state = smtp_client_send_rcptto(client, to_address)) != 1) {
			*errmsg = "Error occurred while specifying recipient to email server.";
			smtp_client_close(client);
			inx_cursor_free(cursor);
			return false;
		}

		nsentto++;
	}

	inx_cursor_free(cursor);

	if (!nsentto) {
		*errmsg = "Mail message could not be sent without recipient.";
		smtp_client_close(client);
		return false;
	}

	// Send the the message.
	if ((state = smtp_client_send_data(client, data)) != 1) {
		*errmsg = "Error occurred while sending email message body.";
		smtp_client_close(client);
		return false;
	}

	// Store the result.
	//*result = st_dupe_opts(MANAGED_T | CONTIGUOUS | HEAP, &(client->line));
	smtp_client_close(client);

	// TODO: smtp_update_transmission_stats() needs to be called here.
	return true;
}