fixed trace bug
[lcr.git] / mail.c
1 /*****************************************************************************\
2 **                                                                           **
3 ** PBX4Linux                                                                 **
4 **                                                                           **
5 **---------------------------------------------------------------------------**
6 ** Copyright: Andreas Eversberg                                              **
7 **                                                                           **
8 ** use mailer to send mail about message                                     **
9 **                                                                           **
10 \*****************************************************************************/ 
11
12 #include "main.h"
13
14 static char *months[] = {
15         "January", "February", "March", "April", "Mai", "June", "July",
16         "August", "September", "October", "November", "December"
17 };
18
19
20 /*
21  * create mail with or without sample
22  * the process creates forks to keep pbx running
23  */
24 struct mail_args {
25         char    email[128];
26         char    filename[256];
27         int     year;
28         int     mon;
29         int     mday;
30         int     hour;
31         int     min;
32         char    callerid[64];
33         char    callerintern[32];
34         char    callername[64];
35         char    terminal[32];
36 };
37
38 static void *mail_child(void *arg)
39 {
40         struct mail_args *args = (struct mail_args *)arg;
41         char *email = args->email;
42         char *filename = args->filename;
43         int year = args->year;
44         int mon = args->mon;
45         int mday = args->mday;
46         int hour = args->hour;
47         int min = args->min;
48         char *callerid = args->callerid;
49         char *callerintern = args->callerintern;
50         char *callername = args->callername;
51         char *terminal = args->terminal;
52
53         char command[128];
54         char buffer[256];
55         char rbuf[54];
56         FILE *ph;
57         int fh;
58         unsigned char e1, e2, e3;
59         int i, n, cnt;
60         unsigned char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
61         struct sched_param schedp;
62         int ret;
63
64         PDEBUG(DEBUG_EPOINT, "child process started for sending a mail\n");
65
66         /* lower priority to keep pbx running fluently */
67         if (options.schedule > 0)
68         {
69                 memset(&schedp, 0, sizeof(schedp));
70                 schedp.sched_priority = 0;
71                 ret = sched_setscheduler(0, SCHED_OTHER, &schedp);
72                 if (ret < 0)
73                 {
74                         PERROR("Scheduling to normal priority failed (errno = %d).\nExitting child process...\n", errno);
75                         goto done;
76                 }
77         }
78
79         /* open process */
80         SPRINT(command, "%s -f%s %s", SENDMAIL, options.email, email);
81         if ((ph = popen(command, "w")) < 0)
82         {
83                 PERROR("Cannot send mail using command '%s'\n", command);
84                 goto done;
85         }
86
87         /* send header */
88         fprintf(ph, "MIME-Version: 1.0\n");
89         fprintf(ph, "Content-Type: multipart/mixed;\n\tboundary=\"next_part\"\n");
90         fprintf(ph, "From: %s <%s>\n", NAME, options.email);
91         fprintf(ph, "To: %s\n", email);
92         fprintf(ph, "Subject: Message from '%s' recorded.\n\n", callerid);
93
94         /* send message */
95         fprintf(ph, "This is a MIME-encapsulated message\n--next_part\n");
96         fprintf(ph, "Content-Type: text/plain; charset=us-ascii\nContent-Transfer-Encoding: 7bit\n\n");
97         fprintf(ph, "\nThe voice box of %s has recorded a message:\n\n * extension: %s\n * from: %s", NAME, terminal, callerid);
98         if (callerintern[0])
99                 fprintf(ph, " (intern %s)", callerintern);
100         if (callername[0])
101                 fprintf(ph, " %s", callername);
102         fprintf(ph, "\n * date: %s %d %d %d:%02d\n\n", months[mon], mday, year+1900, hour, min);
103
104         /* attach audio file */
105         if (filename[0])
106         if ((fh = open(filename, O_RDONLY)))
107         {
108                 while(strchr(filename, '/'))
109                         filename = strchr(filename, '/')+1;
110                 fprintf(ph, "--next_part\n");
111                 if (strlen(filename) >= 4)
112                 if (!strcasecmp(filename+strlen(filename)-4, ".wav"))
113                         fprintf(ph, "Content-Type: audio/x-wav;\n\tname=\"%s\"\n", filename);
114                 fprintf(ph, "Content-Transfer-Encoding: base64\nContent-Disposition: inline;\n\tfilename=\"%s\"\n\n", filename);
115
116                 /* stream from disk and encode */
117                 while(42)
118                 {
119                         /* read exactly one line */
120                         cnt = read(fh, rbuf, 54);
121                         if (cnt <= 0)
122                                 break;
123                         /* encode */
124                         n = cnt;
125                         while (n%3)
126                         {
127                                 rbuf[n] = 0;
128                                 n++;
129                         }
130                         n = n/3;
131                         i = 0;
132                         while(i<n)
133                         {
134                                 e1 = rbuf[i+i+i];
135                                 e2 = rbuf[i+i+i+1];
136                                 e3 = rbuf[i+i+i+2];
137                                 buffer[(i<<2)+3] = base64[e3 & 0x3f];
138                                 buffer[(i<<2)+2] = base64[((e3>>6)+(e2<<2)) & 0x3f];
139                                 buffer[(i<<2)+1] = base64[((e2>>4)+(e1<<4)) & 0x3f];
140                                 buffer[i<<2] = base64[e1 >> 2];
141                                 i++;
142                         }
143                         if ((cnt%3) > 0)
144                                 buffer[(i<<2)-1] = '=';
145                         if ((cnt%3) == 1)
146                                 buffer[(i<<2)-2] = '=';
147                         buffer[(i<<2)] = '\n';
148                         buffer[(i<<2)+1] = '\0';
149                         /* write */
150                         fprintf(ph, "%s", buffer);
151                 }
152
153                 fprintf(ph, "\n\n");
154                 close(fh);
155         } else
156         {
157                 SPRINT(buffer, "-Error- Failed to read audio file: '%s'.\n\n", filename);
158                 fprintf(ph, "%s", buffer);
159                 PERROR("%s", buffer);
160         }
161
162         /* finish mail */
163         fprintf(ph, ".\n");
164
165         /* wait for mail to be sent and close process */
166         pclose(ph);
167
168         done:
169         PDEBUG(DEBUG_EPOINT, "child process done for sending a mail\n");
170
171         /* exit process */
172         FREE(args, sizeof(struct mail_args));
173         amemuse--;
174         return(NULL);
175 }
176
177 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)
178 {
179         struct mail_args *arg;
180         pthread_t tid;
181
182         arg = (struct mail_args *)MALLOC(sizeof(struct mail_args));
183         amemuse++;
184
185         SCPY(arg->email, vbox_email);
186         SCPY(arg->filename, filename);
187         arg->year = vbox_year;
188         arg->mon = vbox_mon;
189         arg->mday = vbox_mday;
190         arg->hour = vbox_hour;
191         arg->min = vbox_min;
192         SCPY(arg->callerid, callerid);
193         SCPY(arg->callerintern, callerintern);
194         SCPY(arg->callername, callername);
195         SCPY(arg->terminal, terminal);
196
197         if ((pthread_create(&tid, NULL, mail_child, arg)<0))
198         {
199                 PERROR("failed to create mail-thread.\n");
200                 return;
201         }
202
203         PDEBUG(DEBUG_EPOINT, "EPOINT '%s' send mail: child process created for sending a mail\n", terminal);
204 }
205