[go: up one dir, main page]

File: SendMail.cpp

package info (click to toggle)
althea 0.5.5-2
  • links: PTS
  • area: main
  • in suites: woody
  • size: 1,196 kB
  • ctags: 725
  • sloc: cpp: 8,194; makefile: 214; sh: 44
file content (277 lines) | stat: -rw-r--r-- 8,236 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
//
//  SendMail.cpp  --  Wrapper function to send mail.  Now uses smtp.
//  -- created 4/11/00  updated 4/11/00
/////////////////////////////////////////

#include "SendMail.h"

extern Althea gAlthea;

// the maximum length for a line
//  -- we might want to change this so that it is
//  determined by the body type.  ie, 1000 for some
//  encoded thing, but for hujman readable make it
//  76.
const int MAX_LINE_LENGTH = 70;

void getProperDate(string &date)  {
   // given string of the form:
   // Thu May 18 16:38:50 2000 (CDT)\n
   // we want:
   // Thu, 18 May 2000 14:43:43 -0500
   string dayNum;
   string year;


   dayNum = date.substr(8,3);
   year = date.substr(20,5);
   date.erase(20,5);
   date.erase(8,3);
   year.replace(4,1," ");
   if (gAlthea.get_Verbose())
     cout << date << endl;
   // now looks like:
   // Thu May 16:38:50 (CDT)
   date.insert(8,year);
   date.insert(4,dayNum);
   date.insert(3,",");
}

int SendMail(Message *M)  {

   /*********************************************
    * our variables				*
    *********************************************/

   string date;
   string bodyData;
   string tmp;
   string::const_iterator i;
   int lineLength;
   int bodyLengthCounter;
   int bodyPartsCounter;
   int prevSpacePos=0;
   time_t tme;

   // hard code our relevant variables until we get
   // this working in a class
   //
   // so how is this stuff going to be passed in?
   // will it be global? will I have to pass the
   // nameof the server and whatnot to SMTPSend?
   string to = M->get_To_Address();
   string from = M->get_Server_Ptr()->get_EMail_Address(); 
   string subject = M->get_Subject() + "\r\n";
   string CC = M->get_CC_Address();
   string otherHeaders;
   string SMTPServer = M->get_Server_Ptr()->get_SMTP_Server_Name();
   string bodyParts[2];

   otherHeaders =  "X-Mailer: Althea (v";
   otherHeaders += VERSION;
   otherHeaders += ")\r\n";

   bodyParts[0] = M->get_Body_Text();

   /*********************************************
    * check to make sure our message is a	*
    * legitimate RFC 821/822 message		*
    *********************************************/

   // make sure we have all the required headers
   // checks occuring in order of severity, from 
   // most to least

   if (to == "")  {
      // no valid recipient.  
      // not a recoverable error

      // "To field unspecified"
      return(1);
   }

   if (from == "")  {
      // sender not specified.

      // "Sender not specified"
      return(2);
   }
   // make sure lines do not exceed MAX_LINE_LENGTH characters
   // and as long as we are looking at everything,
   // make sure it is all valid US-ASCI.
   //
   // i am not sure whether this is the most efficient method
   // of performing this search ornot.  if there is a better 
   // way, most likely by using substring searches, it can
   // be easily added here without hurting anything else.
   for (bodyPartsCounter=0; 
        bodyPartsCounter < (int)bodyParts[bodyPartsCounter].length(); 
        bodyPartsCounter++)  {
      lineLength = 0;
      for (bodyLengthCounter=0; bodyParts[bodyPartsCounter][bodyLengthCounter];
                      bodyLengthCounter++)  {
         if (bodyParts[bodyPartsCounter][bodyLengthCounter]=='\n')  {
            // here is a newline so let's reset our counter
            lineLength = 0;
	    prevSpacePos = bodyLengthCounter;
         }
	 // ok.  think of all the possible word delimeters.
         else if (bodyParts[bodyPartsCounter][bodyLengthCounter]==' ')  {
            // we have a break between words.
	    // remember this position so our line breaks are 
	    // are quite so random
	    prevSpacePos = bodyLengthCounter;
	 }
         
	 if ((lineLength>MAX_LINE_LENGTH) && 
	     (bodyParts[bodyPartsCounter][bodyLengthCounter]!=' '))  {
            // insert a new line for 'em
	    // and remove any leading spaces on the newline
            //bodyParts[bodyPartsCounter].insert(prevSpacePos,"\r");
	    // ^--- for some reason having this in there, in pine at
	    //      least makes it do double lines.  dunno why.
	    //      would be nice to see if we have this same affect
	    //      in other mail clients as well.
            bodyParts[bodyPartsCounter].insert(prevSpacePos,"\n");
            lineLength = 0;
	    prevSpacePos = bodyLengthCounter;
         }
         else  {
            lineLength++;
         }
      }
   }
   /*********************************************
    * lets get all of our stuff attached	*
    * to the body all nice like			*
    *********************************************/
   // get our date header taken care of.
   // this is a lot uglier then is should be,
   // but I don't know how to do it otherwise.
   // there has to be some command that will 
   // get both the date as well as the time zone,
   // but the stuff from ctime and time.h have
   // the timezone seperated.
   // get the current time, local time.
   time(&tme);
   localtime(&tme);
   tmp = ctime(&tme);

   // the string comes with a \n, lets remove that.
   //tmp[tmp.length()-1] = ' ';
   getProperDate(tmp);
   if (gAlthea.get_Verbose())
     cout << tmp;

   // concatenate all of our date sutff together
   date = "Date: " + tmp + "(" + tzname[1] + ")";
   if (gAlthea.get_Verbose())
     cout << date << endl;

   // add headers
   bodyData = date + "\r\n" + "To: " + to + "\r\n";
   if (CC == "") 
	bodyData += otherHeaders + "Subject: " + subject + "\r\n";
   else
	bodyData += "CC: " + CC + "\r\n" + otherHeaders + "Subject: " + subject + "\r\n";


   // add body

   /* First, you need to turn bare LFs into CR LFs to comply with the
    * standards. We do this by deleting CRs, and turning LFs in to CR
    * LFs. There is probably a better way to do it, but I'm not a C++
    * guy. --CRP
    */
   for (i = bodyParts[0].begin(); i != bodyParts[0].end(); i++)  {
     if (*i == '\r') {
       // drop it
     } else if (*i == '\n') {
       bodyData += "\r\n";
     } else {
       bodyData += *i;
     }
   }


   // Before sending, make sure the recipients are compliant with RFC 821.
   // For example, no quotes!
   string temp_to = *new string();
   string temp_cc = *new string();
   unsigned int counter, quote;
   
   list<string> toaddrs;
   
   int begin=0;
   while (to.find(",",begin)<to.length()) {
     toaddrs.push_back(to.substr(begin,to.find(",",begin)-begin));
     begin=to.find(",",begin)+1;     
   }
   toaddrs.push_back(to.substr(begin,to.length()-begin));

   begin=0;
   while (CC.find(",",begin)<CC.length()) {
     toaddrs.push_back(CC.substr(begin,CC.find(",",begin)-begin));
     begin=CC.find(",",begin)+1;     
   }
   toaddrs.push_back(CC.substr(begin,CC.length()-begin));


   for (list<string>::iterator it = toaddrs.begin();
	it != toaddrs.end();
	it++) {

     if ((*it).find("<")<(*it).length()) {
       (*it)=(*it).substr((*it).find("<")+1,(*it).find(">")-(*it).find("<")-1);
     }



     string temp_temp_to="";
     if ((*it).find("\"")<(*it).length()) {
       quote = 0;
       for (counter = 0; counter < (*it).length(); counter++) {
	 if ((*it)[counter] == '"') {
	   if (quote == 1)
	     quote = 0;
	   else if (quote == 0)
	     quote = 1;
	 }
	 else if (quote == 0) 
	   temp_temp_to += (*it)[counter];
       }
     } else
       temp_temp_to=(*it);
     temp_to+=temp_temp_to+", ";
   }
   

   temp_to=temp_to.substr(0,temp_to.length()-2); // get rid of the final ", "
   /*********************************************
    * send the message				*
    *********************************************/

   int port = 25; // default port number
   string errcodestr;
   int errcode;
   // send via SMTP
   // and return whatever error code SMTPSend
   // may have

   //  Note right now, cc and bcc are not implemented!!

   errcode = SMTPSend(SMTPServer,port,temp_to,temp_cc,"",from,bodyData,errcodestr);
   if (errcode == SUCCESS) {
     if (gAlthea.get_Verbose())
       cout << "message sent" << endl;
   } else {
     if (gAlthea.get_Verbose())
       cout << "Message not sent, or quit error. The error code was: " << errcode << endl;
   }


   // Now get rid of "Date: " to store the value back in Message class
   date = date.substr(6);
   M->set_Date(date);
   return(errcode);
}