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