/*****************************************************************************\
**                                                                           **
** PBX4Linux                                                                 **
**                                                                           **
**---------------------------------------------------------------------------**
** Copyright: Andreas Eversberg                                              **
**                                                                           **
** use mailer to send mail about message                                     **
**                                                                           **
\*****************************************************************************/ 

#include "main.h"

static const char *months[] = {
	"January", "February", "March", "April", "Mai", "June", "July",
	"August", "September", "October", "November", "December"
};


/*
 * create mail with or without sample
 * the process creates forks to keep pbx running
 */
struct mail_args {
	char	email[128];
	char	filename[256];
	int	year;
	int	mon;
	int	mday;
	int	hour;
	int	min;
	char	callerid[64];
	char	callerintern[32];
	char	callername[64];
	char	terminal[32];
};

static void *mail_child(void *arg)
{
	struct mail_args *args = (struct mail_args *)arg;
	char *email = args->email;
	char *filename = args->filename;
	int year = args->year;
	int mon = args->mon;
	int mday = args->mday;
	int hour = args->hour;
	int min = args->min;
	char *callerid = args->callerid;
	char *callerintern = args->callerintern;
	char *callername = args->callername;
	char *terminal = args->terminal;

	char command[128];
	char buffer[256];
	char rbuf[54];
	FILE *ph;
	int fh;
	unsigned char e1, e2, e3;
	int i, n, cnt;
	unsigned char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
	struct sched_param schedp;
	int ret;

	PDEBUG(DEBUG_EPOINT, "child process started for sending a mail\n");

	/* lower priority to keep pbx running fluently */
	if (options.schedule > 0)
	{
		memset(&schedp, 0, sizeof(schedp));
		schedp.sched_priority = 0;
		ret = sched_setscheduler(0, SCHED_OTHER, &schedp);
		if (ret < 0)
		{
			PERROR("Scheduling to normal priority failed (errno = %d).\nExitting child process...\n", errno);
			goto done;
		}
	}

	/* open process */
	SPRINT(command, "%s -f%s %s", SENDMAIL, options.email, email);
	if ((ph = popen(command, "w")) < 0)
	{
		PERROR("Cannot send mail using command '%s'\n", command);
		goto done;
	}

	/* send header */
	fprintf(ph, "MIME-Version: 1.0\n");
	fprintf(ph, "Content-Type: multipart/mixed;\n\tboundary=\"next_part\"\n");
 	fprintf(ph, "From: %s <%s>\n", NAME, options.email);
	fprintf(ph, "To: %s\n", email);
	fprintf(ph, "Subject: Message from '%s' recorded.\n\n", callerid);

	/* send message */
	fprintf(ph, "This is a MIME-encapsulated message\n--next_part\n");
	fprintf(ph, "Content-Type: text/plain; charset=us-ascii\nContent-Transfer-Encoding: 7bit\n\n");
 	fprintf(ph, "\nThe voice box of %s has recorded a message:\n\n * extension: %s\n * from: %s", NAME, terminal, callerid);
	if (callerintern[0])
		fprintf(ph, " (intern %s)", callerintern);
	if (callername[0])
		fprintf(ph, " %s", callername);
 	fprintf(ph, "\n * date: %s %d %d %d:%02d\n\n", months[mon], mday, year+1900, hour, min);

	/* attach audio file */
	if ((filename[0]) && ((fh = open(filename, O_RDONLY))))
	{
		while(strchr(filename, '/'))
			filename = strchr(filename, '/')+1;
		fprintf(ph, "--next_part\n");
		if (strlen(filename) >= 4)
		if (!strcasecmp(filename+strlen(filename)-4, ".wav"))
			fprintf(ph, "Content-Type: audio/x-wav;\n\tname=\"%s\"\n", filename);
		fprintf(ph, "Content-Transfer-Encoding: base64\nContent-Disposition: inline;\n\tfilename=\"%s\"\n\n", filename);

		/* stream from disk and encode */
		while(42)
		{
			/* read exactly one line */
			cnt = read(fh, rbuf, 54);
			if (cnt <= 0)
				break;
			/* encode */
			n = cnt;
			while (n%3)
			{
				rbuf[n] = 0;
				n++;
			}
			n = n/3;
			i = 0;
			while(i<n)
			{
				e1 = rbuf[i+i+i];
				e2 = rbuf[i+i+i+1];
				e3 = rbuf[i+i+i+2];
				buffer[(i<<2)+3] = base64[e3 & 0x3f];
				buffer[(i<<2)+2] = base64[((e3>>6)+(e2<<2)) & 0x3f];
				buffer[(i<<2)+1] = base64[((e2>>4)+(e1<<4)) & 0x3f];
				buffer[i<<2] = base64[e1 >> 2];
				i++;
			}
			if ((cnt%3) > 0)
				buffer[(i<<2)-1] = '=';
			if ((cnt%3) == 1)
				buffer[(i<<2)-2] = '=';
			buffer[(i<<2)] = '\n';
			buffer[(i<<2)+1] = '\0';
			/* write */
			fprintf(ph, "%s", buffer);
		}

		fprintf(ph, "\n\n");
		close(fh);
	} else
	{
		SPRINT(buffer, "-Error- Failed to read audio file: '%s'.\n\n", filename);
		fprintf(ph, "%s", buffer);
		PERROR("%s", buffer);
	}

	/* finish mail */
	fprintf(ph, ".\n");

	/* wait for mail to be sent and close process */
	pclose(ph);

	done:
	PDEBUG(DEBUG_EPOINT, "child process done for sending a mail\n");

	/* exit process */
	FREE(args, sizeof(struct mail_args));
	amemuse--;
	return(NULL);
}

void send_mail(char *filename, char *callerid, char *callerintern, char *callername, char *vbox_email, int vbox_year, int vbox_mon, int vbox_mday, int vbox_hour, int vbox_min, char *terminal)
{
	struct mail_args *arg;
	pthread_t tid;

	arg = (struct mail_args *)MALLOC(sizeof(struct mail_args));
	amemuse++;

	SCPY(arg->email, vbox_email);
	SCPY(arg->filename, filename);
	arg->year = vbox_year;
	arg->mon = vbox_mon;
	arg->mday = vbox_mday;
	arg->hour = vbox_hour;
	arg->min = vbox_min;
	SCPY(arg->callerid, callerid);
	SCPY(arg->callerintern, callerintern);
	SCPY(arg->callername, callername);
	SCPY(arg->terminal, terminal);

	if ((pthread_create(&tid, NULL, mail_child, arg)<0))
	{
		PERROR("failed to create mail-thread.\n");
		return;
	}

	PDEBUG(DEBUG_EPOINT, "EPOINT '%s' send mail: child process created for sending a mail\n", terminal);
}

