#line 1026 "../../src/builtin/snarf.m4"
/* -*- buffer-read-only: t -*- vi: set ro:
   THIS FILE IS GENERATED AUTOMATICALLY.  PLEASE DO NOT EDIT.
*/
#line 1026
#ifdef HAVE_CONFIG_H
#line 1026
# include <config.h>
#line 1026
#endif
#line 1026
#include <sys/types.h>
#line 1026

#line 1026
#include "mailfromd.h"
#line 1026
#include "prog.h"
#line 1026
#include "builtin.h"
#line 1026

#line 1026

#line 1066 "../../src/builtin/snarf.m4"

/* End of snarf.m4 */
#line 1 "mail.bi"
/* This file is part of Mailfromd.             -*- c -*-
   Copyright (C) 2006-2025 Sergey Poznyakoff

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 3, or (at your option)
   any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>. */



#include "msg.h"

static int
_send(eval_environ_t env,
      const char *mailer_url, char *to, char *from, mu_message_t msg,
      void (*destroy)(void*), void *ptr)
{
	int status;
	mu_mailer_t mailer;
	mu_address_t to_addr = NULL;
	mu_address_t from_addr = NULL;
	
	if (!mailer_url)
		mu_mailer_get_url_default(&mailer_url);
	status = mu_mailer_create(&mailer, mailer_url);
	if (status) {
		destroy(ptr);
		(
#line 36
	env_throw_bi(env, mfe_failure, NULL, _("cannot create mailer `%s': %s"),mailer_url,mu_strerror(status))
#line 36
);
#line 39
	}

	if (to) {
		status = mu_address_create(&to_addr, to);
		if (status) {
			destroy(ptr);
			mu_mailer_destroy(&mailer);
			(
#line 46
	env_throw_bi(env, mfe_failure, NULL, _("bad recipient address `%s': %s"),to,mu_strerror(status))
#line 46
);
#line 49
		}
	}
	
	if (!from || from[0] == 0)
		from = "<>";
	status = mu_address_create(&from_addr, from);
	if (status) {
		mu_address_destroy(&to_addr);
		mu_mailer_destroy(&mailer);
		destroy(ptr);
		(
#line 59
	env_throw_bi(env, mfe_failure, NULL, _("bad sender address `%s': %s"),from,mu_strerror(status))
#line 59
);
#line 62
	}
	
	/* FIXME: mailer flags? */
	status = mu_mailer_open(mailer, 0);
	if (status) {
		mu_address_destroy(&to_addr);
		mu_address_destroy(&from_addr);
		mu_mailer_destroy(&mailer);
		destroy(ptr);
		(
#line 71
	env_throw_bi(env, mfe_failure, NULL, _("opening mailer `%s' failed: %s"),mailer_url,mu_strerror (status))
#line 71
);
#line 74
	}
	
	status = mu_mailer_send_message(mailer, msg, from_addr, to_addr);
	mu_address_destroy(&to_addr);
	mu_address_destroy(&from_addr);
	mu_mailer_destroy(&mailer);
	destroy(ptr);
		if (!(status == 0))
#line 81
		(
#line 81
	env_throw_bi(env, mfe_failure, NULL, _("cannot send message: %s"),mu_strerror(status))
#line 81
)
#line 83
;
	return 0;
}

static void
_destroy_msg(void *ptr)
{
	mu_message_t msg = ptr;
	mu_message_destroy(&msg, mu_message_get_owner(msg));
}

void
#line 94
bi_send_mail(eval_environ_t env)
#line 94

#line 94

#line 94 "mail.bi"
{
#line 94
	
#line 94

#line 94
        char *  text;
#line 94
        char *  to;
#line 94
        char *  from;
#line 94
        char *  mailer_url;
#line 94
        
#line 94
        long __bi_argcnt;
#line 94
        get_numeric_arg(env, 0, &__bi_argcnt);
#line 94
        get_string_arg(env, 1, &text);
#line 94
        if (__bi_argcnt > 1)
#line 94
                get_string_arg(env, 2, &to);
#line 94
        if (__bi_argcnt > 2)
#line 94
                get_string_arg(env, 3, &from);
#line 94
        if (__bi_argcnt > 3)
#line 94
                get_string_arg(env, 4, &mailer_url);
#line 94
        
#line 94
        adjust_stack(env, __bi_argcnt + 1);
#line 94

#line 94

#line 94
	if (builtin_module_trace(BUILTIN_IDX_mail))
#line 94
		prog_trace(env, "send_mail %s %s %s %s",text, ((__bi_argcnt > 1) ? to : ""), ((__bi_argcnt > 2) ? from : ""), ((__bi_argcnt > 3) ? mailer_url : ""));;

{
	mu_message_t msg = NULL;
	mu_stream_t stream = NULL;
	
	mu_message_create(&msg, NULL);
	mu_static_memory_stream_create(&stream, text, strlen(text));
	mu_message_set_stream(msg, stream, mu_message_get_owner(msg));
	
	_send(env, ((__bi_argcnt > 3) ? mailer_url : NULL),
	      ((__bi_argcnt > 1) ? to : NULL),
              ((__bi_argcnt > 2) ? from : NULL), msg, _destroy_msg, msg);
	mu_stream_unref(stream);
}

#line 109
        env_function_cleanup_flush(env, CLEANUP_RETURN);
#line 109
	return;
#line 109
}

void
#line 111
bi_send_message(eval_environ_t env)
#line 111

#line 111

#line 111 "mail.bi"
{
#line 111
	
#line 111

#line 111
        long  nmsg;
#line 111
        char *  to;
#line 111
        char *  from;
#line 111
        char *  mailer_url;
#line 111
        
#line 111
        long __bi_argcnt;
#line 111
        get_numeric_arg(env, 0, &__bi_argcnt);
#line 111
        get_numeric_arg(env, 1, &nmsg);
#line 111
        if (__bi_argcnt > 1)
#line 111
                get_string_arg(env, 2, &to);
#line 111
        if (__bi_argcnt > 2)
#line 111
                get_string_arg(env, 3, &from);
#line 111
        if (__bi_argcnt > 3)
#line 111
                get_string_arg(env, 4, &mailer_url);
#line 111
        
#line 111
        adjust_stack(env, __bi_argcnt + 1);
#line 111

#line 111

#line 111
	if (builtin_module_trace(BUILTIN_IDX_mail))
#line 111
		prog_trace(env, "send_message %lu %s %s %s",nmsg, ((__bi_argcnt > 1) ? to : ""), ((__bi_argcnt > 2) ? from : ""), ((__bi_argcnt > 3) ? mailer_url : ""));;

{
	mu_message_t msg = bi_message_from_descr(env, nmsg);
	_send(env, ((__bi_argcnt > 3) ? mailer_url : NULL),
	      ((__bi_argcnt > 1) ? to : NULL),
              ((__bi_argcnt > 2) ? from : NULL), msg, _destroy_msg, msg);
}

#line 119
        env_function_cleanup_flush(env, CLEANUP_RETURN);
#line 119
	return;
#line 119
}

static void
add_headers(mu_message_t msg, char *headers)
{
	mu_stream_t stream = NULL;
	mu_header_t hdr = NULL;
	size_t len;

	if (!headers)
		return;
	
	len = strlen(headers);
	mu_message_get_header(msg, &hdr);
	
	mu_header_get_streamref(hdr, &stream);
	mu_stream_seek(stream, -1, MU_SEEK_END, NULL);
	mu_stream_write(stream, headers, len, NULL);
	if (len < 2 || memcmp(headers + len - 2, "\n\n", 2)) {
		if (len > 1 && headers[len-1] == '\n')
			mu_stream_write(stream, "\n", 1, NULL);
		else
			mu_stream_write(stream, "\n\n", 2, NULL);
	}
	mu_stream_unref(stream);
}

void
#line 146
bi_send_text(eval_environ_t env)
#line 146

#line 146

#line 146 "mail.bi"
{
#line 146
	
#line 146

#line 146
        char *  text;
#line 146
        char *  headers;
#line 146
        char *  to;
#line 146
        char *  from;
#line 146
        char *  mailer_url;
#line 146
        
#line 146
        long __bi_argcnt;
#line 146
        get_numeric_arg(env, 0, &__bi_argcnt);
#line 146
        get_string_arg(env, 1, &text);
#line 146
        get_string_arg(env, 2, &headers);
#line 146
        if (__bi_argcnt > 2)
#line 146
                get_string_arg(env, 3, &to);
#line 146
        if (__bi_argcnt > 3)
#line 146
                get_string_arg(env, 4, &from);
#line 146
        if (__bi_argcnt > 4)
#line 146
                get_string_arg(env, 5, &mailer_url);
#line 146
        
#line 146
        adjust_stack(env, __bi_argcnt + 1);
#line 146

#line 146

#line 146
	if (builtin_module_trace(BUILTIN_IDX_mail))
#line 146
		prog_trace(env, "send_text %s %s %s %s %s",text, headers, ((__bi_argcnt > 2) ? to : ""), ((__bi_argcnt > 3) ? from : ""), ((__bi_argcnt > 4) ? mailer_url : ""));;

{
	mu_message_t msg = NULL;
	mu_body_t body = NULL;
	mu_stream_t stream = NULL;
	
	mu_message_create(&msg, NULL);

	mu_message_get_body(msg, &body);
	mu_body_get_streamref(body, &stream);
	mu_stream_write(stream, text, strlen(text), NULL);
	mu_stream_unref(stream);
	
	add_headers(msg, headers);
	_send(env, ((__bi_argcnt > 4) ? mailer_url : NULL), ((__bi_argcnt > 2) ? to : NULL), 
              ((__bi_argcnt > 3) ? from : NULL), msg, _destroy_msg, msg);
}

#line 164
        env_function_cleanup_flush(env, CLEANUP_RETURN);
#line 164
	return;
#line 164
}


static void
mime_create_reason(mu_mime_t mime, const char *sender, const char *text)
{
	mu_message_t newmsg;
	mu_stream_t stream;
	time_t t;
	struct tm *tm;
	mu_body_t body;
	mu_header_t hdr;
	char datestr[80];
	static char *content_header =
		"Content-Type: text/plain;charset=US-ASCII\n" /* FIXME! */
		"Content-Transfer-Encoding: 8bit\n";
 
	mu_message_create(&newmsg, NULL);
	mu_message_get_body(newmsg, &body);
	mu_body_get_streamref(body, &stream);

	time(&t);
	tm = localtime(&t);
	mu_strftime(datestr, sizeof datestr, "%a, %b %d %H:%M:%S %Y %Z", tm);

	mu_stream_printf(stream,
			 "\n"
			 "The original message was received at %s from %s.\n",
			 datestr, sender);

	mu_stream_write(stream, text, strlen(text), NULL);
	mu_stream_flush(stream);
	mu_stream_unref(stream);
	mu_header_create(&hdr, content_header, strlen(content_header));
	mu_message_set_header(newmsg, hdr, NULL);
	mu_mime_add_part(mime, newmsg);
	mu_message_unref(newmsg);
}

static void
mime_create_ds(mu_mime_t mime, char *recpt)
{
	mu_message_t newmsg;
	mu_stream_t stream;
	mu_header_t hdr;
	mu_body_t body;
	char datestr[80];
	time_t t;
	struct tm *tm;
	
	time(&t);
	tm = localtime(&t);
	mu_strftime(datestr, sizeof datestr, "%a, %b %d %H:%M:%S %Y %Z", tm);

	mu_message_create(&newmsg, NULL);
	mu_message_get_header(newmsg, &hdr); 
	mu_header_set_value(hdr, "Content-Type", "message/delivery-status", 1);
	mu_message_get_body(newmsg, &body);
	mu_body_get_streamref(body, &stream);
	mu_stream_printf(stream, "Reporting-UA: %s\n", PACKAGE_STRING);
	mu_stream_printf(stream, "Arrival-Date: %s\n", datestr);
	mu_stream_printf(stream, "Final-Recipient: RFC822; %s\n",
			 recpt ? recpt : "unknown");
	mu_stream_printf(stream, "%s", "Action: deleted\n");
	mu_stream_printf(stream, "%s",
			 "Disposition: automatic-action/"
			 "MDN-sent-automatically;deleted\n");
	mu_stream_printf(stream, "Last-Attempt-Date: %s\n", datestr);
	mu_stream_unref(stream);
	mu_mime_add_part(mime, newmsg);
	mu_message_unref(newmsg);
}

/* Quote original message */
static int
mime_create_quote(mu_mime_t mime, mu_stream_t istream)
{
	mu_message_t newmsg;
	mu_stream_t ostream;
	mu_header_t hdr;
	mu_body_t body;
	char *buf = NULL;
	size_t bufsize = 0;
	
	mu_message_create(&newmsg, NULL);
	mu_message_get_header(newmsg, &hdr); 
	mu_header_set_value(hdr, "Content-Type", "message/rfc822", 1);
	mu_message_get_body (newmsg, &body);
	mu_body_get_streamref(body, &ostream);
	/* Skip envelope line */
	mu_stream_getline(istream, &buf, &bufsize, NULL);
	free(buf);
	mu_stream_copy(ostream, istream, 0, NULL);
	mu_stream_unref(ostream);
	mu_mime_add_part(mime, newmsg);
	mu_message_unref(newmsg);
	return 0;
}
  
static int
build_mime(mu_mime_t *pmime, mu_stream_t msgstr,
	   char *sender, char *recpt,
	   char *text)
{
	mu_mime_t mime = NULL;
	int status;
  
	mu_mime_create(&mime, NULL, 0);
	mime_create_reason(mime, sender, text);
	mime_create_ds(mime, recpt);
        status = mime_create_quote(mime, msgstr);
	if (status) {
		mu_mime_destroy(&mime);
		return status;
	}
	*pmime = mime;
	return 0;
}

static void
_destroy_mime(void *ptr)
{
	mu_mime_t mime = ptr;
	mu_mime_destroy(&mime);
}



void
#line 292
bi_create_dsn(eval_environ_t env)
#line 292

#line 292

#line 292 "mail.bi"
{
#line 292
	  mu_stream_t mstr;
#line 292

#line 292
	
#line 292

#line 292
        char *  sender;
#line 292
        char *  recpt;
#line 292
        char *  text;
#line 292
        char *  headers;
#line 292
        char *  from;
#line 292
        
#line 292
        long __bi_argcnt;
#line 292
        get_numeric_arg(env, 0, &__bi_argcnt);
#line 292
        get_string_arg(env, 1, &sender);
#line 292
        get_string_arg(env, 2, &recpt);
#line 292
        get_string_arg(env, 3, &text);
#line 292
        if (__bi_argcnt > 3)
#line 292
                get_string_arg(env, 4, &headers);
#line 292
        if (__bi_argcnt > 4)
#line 292
                get_string_arg(env, 5, &from);
#line 292
        
#line 292
        adjust_stack(env, __bi_argcnt + 1);
#line 292

#line 292
{
#line 292
	  int rc = env_get_stream(env,&mstr);
#line 292
	  	if (!(rc == 0))
#line 292
		(
#line 292

#line 292
	mu_stream_unref(mstr),
#line 292
	env_throw_bi(env, mfe_failure, "create_dsn", "cannot obtain capture stream reference: %s",mu_strerror(rc))
#line 292
)
#line 292
;
#line 292
	}
#line 292
	if (builtin_module_trace(BUILTIN_IDX_mail))
#line 292
		prog_trace(env, "create_dsn %s %s %s %s %s",sender, recpt, text, ((__bi_argcnt > 3) ? headers : ""), ((__bi_argcnt > 4) ? from : ""));;

{
	int rc;
	mu_mime_t mime;
	mu_message_t msg;
	
	rc = build_mime(&mime, mstr, sender, recpt, text);
		if (!(rc == 0))
#line 300
		(
#line 300

#line 300
	mu_stream_unref(mstr),
#line 300
	env_throw_bi(env, mfe_failure, "create_dsn", _("cannot create DSN: %s"),mu_strerror(rc))
#line 300
)
#line 303
;

	mu_mime_get_message(mime, &msg);
	add_headers(msg, ((__bi_argcnt > 3) ? headers : NULL));
	rc = bi_message_register(env, NULL, msg, MF_MSG_STANDALONE);
	if (rc < 0) {
		mu_message_destroy(&msg, mu_message_get_owner(msg));
		(
#line 310

#line 310
	mu_stream_unref(mstr),
#line 310
	env_throw_bi(env, mfe_failure, "create_dsn", _("no more message slots available"))
#line 310
);
#line 312
	}
	
#line 313
do {
#line 313
  push(env, (STKVAL)(mft_number)(rc));
#line 313
  goto endlab;
#line 313
} while (0);
}
endlab:
#line 315

#line 315
	mu_stream_unref(mstr);
#line 315
        env_function_cleanup_flush(env, CLEANUP_RETURN);
#line 315
	return;
#line 315
}



void
#line 319
bi_send_dsn(eval_environ_t env)
#line 319

#line 319

#line 319 "mail.bi"
{
#line 319
	  mu_stream_t mstr;
#line 319

#line 319
	
#line 319

#line 319
        char *  to;
#line 319
        char *  sender;
#line 319
        char *  recpt;
#line 319
        char *  text;
#line 319
        char *  headers;
#line 319
        char *  from;
#line 319
        char *  mailer_url;
#line 319
        
#line 319
        long __bi_argcnt;
#line 319
        get_numeric_arg(env, 0, &__bi_argcnt);
#line 319
        get_string_arg(env, 1, &to);
#line 319
        get_string_arg(env, 2, &sender);
#line 319
        get_string_arg(env, 3, &recpt);
#line 319
        get_string_arg(env, 4, &text);
#line 319
        if (__bi_argcnt > 4)
#line 319
                get_string_arg(env, 5, &headers);
#line 319
        if (__bi_argcnt > 5)
#line 319
                get_string_arg(env, 6, &from);
#line 319
        if (__bi_argcnt > 6)
#line 319
                get_string_arg(env, 7, &mailer_url);
#line 319
        
#line 319
        adjust_stack(env, __bi_argcnt + 1);
#line 319

#line 319
{
#line 319
	  int rc = env_get_stream(env,&mstr);
#line 319
	  	if (!(rc == 0))
#line 319
		(
#line 319

#line 319
	mu_stream_unref(mstr),
#line 319
	env_throw_bi(env, mfe_failure, "send_dsn", "cannot obtain capture stream reference: %s",mu_strerror(rc))
#line 319
)
#line 319
;
#line 319
	}
#line 319
	if (builtin_module_trace(BUILTIN_IDX_mail))
#line 319
		prog_trace(env, "send_dsn %s %s %s %s %s %s %s",to, sender, recpt, text, ((__bi_argcnt > 4) ? headers : ""), ((__bi_argcnt > 5) ? from : ""), ((__bi_argcnt > 6) ? mailer_url : ""));;
#line 321

{
	int status;
	mu_mime_t mime;
	mu_message_t newmsg;
	
	status = build_mime(&mime, mstr, sender, recpt, text);
		if (!(status == 0))
#line 328
		(
#line 328

#line 328
	mu_stream_unref(mstr),
#line 328
	env_throw_bi(env, mfe_failure, "send_dsn", _("cannot create DSN: %s"),mu_strerror(status))
#line 328
)
#line 331
;

	mu_mime_get_message(mime, &newmsg);
	add_headers(newmsg, ((__bi_argcnt > 4) ? headers : NULL));
	_send(env, ((__bi_argcnt > 6) ? mailer_url : NULL), to, 
              ((__bi_argcnt > 5) ? from : NULL), newmsg, _destroy_mime, mime);
}

#line 338

#line 338
	mu_stream_unref(mstr);
#line 338
        env_function_cleanup_flush(env, CLEANUP_RETURN);
#line 338
	return;
#line 338
}

#line 1026 "../../src/builtin/snarf.m4"

#line 1026

#line 1026

#line 1026
void
#line 1026
mail_init_builtin(void)
#line 1026
{
#line 1026
	
#line 1026
	#line 94 "mail.bi"
va_builtin_install_ex("send_mail", bi_send_mail, 0, dtype_unspecified, 4, 3, 0|0, dtype_string, dtype_string, dtype_string, dtype_string);
#line 111 "mail.bi"
va_builtin_install_ex("send_message", bi_send_message, 0, dtype_unspecified, 4, 3, 0|0, dtype_number, dtype_string, dtype_string, dtype_string);
#line 146 "mail.bi"
va_builtin_install_ex("send_text", bi_send_text, 0, dtype_unspecified, 5, 3, 0|0, dtype_string, dtype_string, dtype_string, dtype_string, dtype_string);
#line 292 "mail.bi"
va_builtin_install_ex("create_dsn", bi_create_dsn, STATMASK(smtp_state_eom), dtype_number, 5, 2, MFD_BUILTIN_CAPTURE|0, dtype_string, dtype_string, dtype_string, dtype_string, dtype_string);
#line 319 "mail.bi"
va_builtin_install_ex("send_dsn", bi_send_dsn, STATMASK(smtp_state_eom), dtype_unspecified, 7, 3, MFD_BUILTIN_CAPTURE|0, dtype_string, dtype_string, dtype_string, dtype_string, dtype_string, dtype_string, dtype_string);

#line 1026 "../../src/builtin/snarf.m4"
	
#line 1026
}
#line 1026 "../../src/builtin/snarf.m4"

