/* NOT to be confused with similar features inside surgemail
 which relies on surgemail to work.
*/
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <time.h>
#include "tcplib.h"
#include "smail.h"
#include "lprintf.h"
#include "lib.h"
#include "decode.h"
#include "thread.h"
#include "mime.h"
#ifdef USE_DFOPEN
#include "debug.h"
#include "dfopen.h"
#endif

int  imsg(const char * arg_list, ...);


#ifndef FALSE
#define FALSE 0
#endif

#ifndef TRUE
#define TRUE (!FALSE)
#endif
static int debug;
int smail_set_debug(int x)
{
	debug = x;
	return TRUE;
}
int smail_new(Smail **im, char *host, int port, FILE *log)
{
	Smail *m;
	char tmp[BFSZ];
	m = calloc(sizeof(Smail),1);
	*im = m;
	
	m->log=log;

	/* Open connection etc */
	if (port==0) port=25;

	tcp_new(&m->c);

	if (!tcp_open(m->c, host, port, NULL)) {
		lprintf(m->reason,BFSZ-1,"open (%s:%d) failed %s",host,port,tcp_error(m->c,tmp));
		imsg("smail: %s\n",m->reason);
		return FALSE;
	}
	imsg("smail: open worked %s\n",host);
	if (port==465){
		char reason[BFSZ];
		if (!tcp_ssl_init(m->c,FALSE,NULL,reason)) {
			imsg("smail: %s\n",reason);
			return FALSE;
		}
	}

	if (!smail_response(m)) return FALSE;
	imsg("smail: open response %s\n",m->reason);
	return TRUE;
}
char *smail_error(Smail *m)
{
	return m->reason;
}
int smail_response(Smail *m)
{
	char tmp[BFSZ],tstr[BFSZ];
	int line=0;

multiline:
	if (!tcp_readline(m->c,m->reason,BFSZ-1)) {
		lprintf(m->reason,BFSZ-1,"%s",tcp_error(m->c,tmp));
		imsg("smail: read failed (%s)\n",m->reason);
		return FALSE;
	}
	line++;
	if(lib_strlen(m->reason)>4 && m->reason[3]=='-' && line<100) goto multiline;

	imsg("smail: got (%s)\n",m->reason);
	if(m->log){ 
		lib_emsg_time(tstr);
		fprintf(m->log,"%s:SERVER:%d(%02d){%s}\n",tstr,(int) th_id(),(int) lib_strlen(m->reason),m->reason);
	}
	if(m->log_pass){
		imsg("smail: (surgeweb setting smtpauth_logpass) RESPONSE:%s", m->reason);
	}

	if (debug) printf("response %s\n",m->reason);
	if (atoi(m->reason)<200) return FALSE;
	if (atoi(m->reason)>399) return FALSE;
	return TRUE;
}
int smail_addheaders(Smail *m, int t)
{
	m->addheaders = TRUE;
	return TRUE;
}
int smail_set_host(Smail *m, char *host)
{
	strncpy(m->host,host,BFSZ-1);
	m->host[BFSZ-1] = 0;
	return TRUE;
}
int smail_set_helo(Smail *m, char *helo)
{
	ncpy(m->helo,helo,BFSZ-1);
	return TRUE;
}
int smail_internal(Smail *m, char *xpass)
{
	smail_printf(m,"XINTERNAL %s\r\n",xpass);
	imsg("smail: send xinternal\n");
	if (!smail_response(m)) {
		imsg("smail: send xinternal failed %s\n",smail_error(m));
		return FALSE;
	}
	return TRUE;
}

int smail_header(Smail *m,char *envfrom,char *from,char *to,char *cc, char *bcc, char *subject)
{
	return smail_header_login(m,envfrom,from,to,cc,bcc,subject,NULL,NULL);
}

int smail_header_login(Smail *m,char *envfrom,char *from,char *to,char *cc, char *bcc, char *subject, char *user, char *pass)
{
	char tmp[BFSZ];
	char host[BFSZ];
	char helo[BFSZ];
	ncpy(host,tcp_hostname(tmp),BFSZ-1);
	if (lib_strlen(m->host)>0) ncpy(host,m->host,BFSZ-1);
	ncpy(helo,host,BFSZ-1);
	if (lib_strlen(m->helo)>0) ncpy(helo,m->helo,BFSZ-1);
	smail_printf(m,"HELO %s\r\n",helo);
	imsg("smail: send helo\n");
	if (!smail_response(m)) return FALSE;


	if (user!=NULL) {
		char userpass[BFSZ];
		smail_printf(m,"AUTH LOGIN\r\n");
		if (!smail_response(m)) return FALSE;

		mime_encode_base64_bad(user,lib_strlen(user)+1,userpass,300);
		if (!smail_printf(m,"%s\r\n",userpass)) return FALSE;
		if (!smail_response(m)) return FALSE;

		mime_encode_base64_bad(pass,lib_strlen(pass)+1,userpass,300);
		if (!smail_printf(m,"%s\r\n",userpass)) return FALSE;
		if (!smail_response(m)) return FALSE;
	}
	smail_printf(m,"MAIL FROM:<%s>\r\n",envfrom);
	if (!smail_response(m)) return FALSE;

	imsg("smail: send rcpttop %s\n",to);
	smail_printf(m,"RCPT TO:<%s>\r\n",to);
	if (!smail_response(m)) return FALSE;
	if (lib_strlen(cc)>0) {
		smail_printf(m,"RCPT TO:<%s>\r\n",cc);
		if (!smail_response(m)) return FALSE;
	}
	if (lib_strlen(bcc)>0) {
		smail_printf(m,"RCPT TO:<%s>\r\n",bcc);
		if (!smail_response(m)) return FALSE;
	}
	smail_printf(m,"DATA\r\n");
	if (!smail_response(m)) return FALSE;
	imsg("smail: send data\n");

	if (!m->addheaders) {
		smail_printf(m,"From: %s\r\n", from);
		if (lib_strlen(cc)>0) smail_printf(m,"Cc: %s\r\n", cc);
		smail_printf(m,"Subject: %s\r\n", subject);
		smail_printf(m,"To: %s\r\n", to);
		if (!smail_printf(m,"\r\n")) return FALSE;
	}
	imsg("smail: sent message %s\n",m->reason);
	return TRUE;
}
#include "vsnprintf.h"
int smail_printf(Smail *m,char *arg_list,...)
{
    va_list arg_ptr;
    char *format;
 	char output[2000];
	char tmp[BFSZ],tstr[BFSZ];

    va_start(arg_ptr, arg_list);
    format = (char *)  arg_list;
    vsnprintf(output,1000, format, arg_ptr); output[999] = 0;

	if (!tcp_write(m->c,output,lib_strlen(output))) {
		lprintf(m->reason,BFSZ-1,"smail_printf: %s",tcp_error(m->c,tmp));
		imsg("tcp_write did fail\n");
		return FALSE;	
	}

// MW: This does not seem to "do anything at all"?? removing
//	s = strchr(output,'\n');
//	if (s!=NULL) if (s>output) if (s[-1]!='\r') imsg("smail line termination MUST be crlf only found LF\n");
//	strncpy(clean,output,100); clean[100] = 0;
//	s = strchr(clean,'\r'); if (s!=NULL) *s = 0;

	if(m->log) {
		lib_emsg_time(tstr);
		ncpy(tmp,output,BFSZ-1);
		lib_strip_crlf(tmp);
		fprintf(m->log,"%s:CLIENT:%d(%02d){%s}\n",tstr,(int) th_id(),(int) lib_strlen(tmp),tmp);
	}
	//dmsg("smail_printf (%s)\n",clean);
	return TRUE;
}
int smail_send_file(Smail *m, char *fname)
{
	FILE *f;
	char bf[BFSZ];
	char *s;
	f = fopen(fname,"r");
	if (f==NULL) return FALSE;
	for (;!feof(f);) {
		if (fgets(bf,BFSZ-1,f)==NULL) break;
		s = strchr(bf,'\n'); if (s!=NULL) *s = 0;
		s = strchr(bf,'\r'); if (s!=NULL) *s = 0;
		smail_printf(m,"%s\r\n",bf);
	}
	fclose(f);
	return TRUE;
}
int smail_send(Smail *m)
{
	if (debug) printf("sending dot \n");
	smail_printf(m,".\r\n");
	if (!smail_response(m)) return FALSE;
	smail_printf(m,"QUIT\r\n");
	if (!smail_response(m)) return FALSE;
	tcp_close_nice(m->c);
	return TRUE;
}
int smail_close(Smail **out)
{
	Smail *o= *out;
	if (o->c!=NULL) tcp_free(&o->c);
	if (o->log) fclose(o->log);
	free(*out);
	*out = NULL;
	return TRUE;
}


int smail_write(Smail *m,char *str, int len)
{
	return tcp_write(m->c,str,len);
}

int smail_login(Smail *m, char *user, char *pass)
{
	char bf[BFSZ];
	int n;

	if(m->log_pass){
		imsg("smail: (surgeweb setting smtpauth_logpass) %s %s", user, pass);
	}
	 
	smail_printf(m,"AUTH %s\r\n","LOGIN");
	if (!smail_response(m)) return FALSE;
	decode_base64(m->reason+4, bf, BFSZ);		// Should now contain "username" - we need to check?

	n=lib_strlen(user); 
	if (n>BFSZ-1) return FALSE;
	encode_base64(user,bf,n+1);
	smail_printf(m,"%s\r\n",bf);
	if (!smail_response(m)) return FALSE;
	decode_base64(m->reason+4, bf, BFSZ);		// Should now contain "password" - we need to check?

	n=lib_strlen(pass); 
	if (n>BFSZ-1) return FALSE;
	encode_base64(pass,bf,n+1);
	smail_printf(m,"%s\r\n",bf);
	if (!smail_response(m)) return FALSE;

	return TRUE;
}

int smail_send_rcpts(Smail *msg, Pair *rcpts_to, int dsn, char *result, int *nrcpt)
{
	char tmp[BFSZ];
	Pair *p;
	for(p=rcpts_to; p; p=p->next){
		if(dsn)
			smail_printf(msg,"RCPT TO:<%s> NOTIFY=SUCCESS,FAILURE ORCPT=rfc822;%s\r\n",p->var,p->var);
		else
			smail_printf(msg,"RCPT TO:<%s>\r\n",p->var);
		if (smail_response(msg)){ 
			(*nrcpt)++;
			continue;
		}
		// this rcpt failed (that is ok for now, report later)
		if (*result) 
			ncat(result,"<br>",BFSZ-1);
		lprintf(tmp,BFSZ,"%s : %s",p->var,msg->reason);
		ncat(result,tmp,BFSZ-1);
	}
	return TRUE;
}

int smail_sentstore(Smail *m, char *folder)
{
    
	smail_printf(m,"XSENTSTORE \"%s\"\r\n",folder);
	if (!smail_response(m)) return FALSE;
    
	return TRUE;
}


