]> err.no Git - scalable-opengroupware.org/blob - SoObjects/SOGo/SOGoMailer.m
git-svn-id: http://svn.opengroupware.org/SOGo/inverse/trunk@1192 d1b88da0-ebda-0310...
[scalable-opengroupware.org] / SoObjects / SOGo / SOGoMailer.m
1 /* SOGoMailer.m - this file is part of SOGo
2  *
3  * Copyright (C) 2007 Inverse groupe conseil
4  *
5  * Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
6  *
7  * This file is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2, or (at your option)
10  * any later version.
11  *
12  * This file is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; see the file COPYING.  If not, write to
19  * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */
22
23 #import <Foundation/NSArray.h>
24 #import <Foundation/NSEnumerator.h>
25 #import <Foundation/NSException.h>
26 #import <Foundation/NSString.h>
27 #import <Foundation/NSUserDefaults.h>
28
29 #import <NGObjWeb/NSException+HTTP.h>
30 #import <NGExtensions/NSObject+Logs.h>
31 #import <NGMail/NGSendMail.h>
32 #import <NGMail/NGSmtpClient.h>
33 #import <NGMime/NGMimePartGenerator.h>
34
35 #import "NSString+Utilities.h"
36 #import "SOGoMailer.h"
37
38 #define defaultMailingMechanism @"sendmail"
39 #define defaultSMTPServer @"localhost"
40
41 @implementation SOGoMailer
42
43 + (id) sharedMailer
44 {
45   static id sharedMailer = nil;
46
47   if (!sharedMailer)
48     sharedMailer = [self new];
49
50   return sharedMailer;
51 }
52
53 - (id) init
54 {
55   NSUserDefaults *ud;
56
57   if ((self = [super init]))
58     {
59       ud = [NSUserDefaults standardUserDefaults];
60       mailingMechanism = [ud stringForKey: @"SOGoMailingMechanism"];
61       if (mailingMechanism)
62         {
63           if (!([mailingMechanism isEqualToString: @"sendmail"]
64                 || [mailingMechanism isEqualToString: @"smtp"]))
65             {
66               [self logWithFormat: @"mechanism '%@' is invalid and"
67                     @" should be set to 'sendmail' or 'smtp' instead",
68                     mailingMechanism];
69               [self logWithFormat: @"falling back to default '%@' mechanism",
70                     defaultMailingMechanism];
71               mailingMechanism = defaultMailingMechanism;
72             }
73         }
74       else
75         {
76           [self logWithFormat: @"default mailing mechanism set to '%@'",
77                 defaultMailingMechanism];
78           mailingMechanism = defaultMailingMechanism;
79         }
80       [mailingMechanism retain];
81
82       if ([mailingMechanism isEqualToString: @"smtp"])
83         {
84           smtpServer = [ud stringForKey: @"SOGoSMTPServer"];
85           if (!smtpServer)
86             {
87               [self logWithFormat: @"default smtp server set to '%@'",
88                     defaultSMTPServer];
89               smtpServer = defaultSMTPServer;
90             }
91           [smtpServer retain];
92         }
93       else
94         smtpServer = nil;
95     }
96
97   return self;
98 }
99
100 - (void) dealloc
101 {
102   [mailingMechanism release];
103   [smtpServer release];
104   [super dealloc];
105 }
106
107 - (NSException *) _sendmailSendData: (NSData *) mailData
108                        toRecipients: (NSArray *) recipients
109                              sender: (NSString *) sender
110 {
111   NSException *result;
112   NGSendMail *mailer;
113
114   mailer = [NGSendMail sharedSendMail];
115   if ([mailer isSendMailAvailable])
116     result = [mailer sendMailData: mailData
117                      toRecipients: recipients
118                      sender: sender];
119   else
120     result = [NSException exceptionWithHTTPStatus: 500
121                           reason: @"cannot send message:"
122                           @" no sendmail binary!"];
123
124   return result;
125 }
126
127 - (NSException *) _sendMailData: (NSData *) mailData
128                      withClient: (NGSmtpClient *) client
129                   andRejections: (unsigned int) toErrors
130 {
131   NSException *result;
132
133   if (toErrors > 0)
134     [self logWithFormat: @"sending email despite address rejections"];
135   if ([client sendData: mailData])
136     result = nil;
137   else
138     result = [NSException exceptionWithHTTPStatus: 500
139                           reason: @"cannot send message:"
140                           @" (smtp) failure when sending data"];
141
142   return result;
143 }
144
145 - (NSException *) _smtpSendData: (NSData *) mailData
146                    toRecipients: (NSArray *) recipients
147                          sender: (NSString *) sender
148 {
149   NGSmtpClient *client;
150   NSEnumerator *addresses;
151   NSString *currentTo;
152   unsigned int toErrors;
153   NSException *result;
154
155   client = [NGSmtpClient smtpClient];
156   if ([client connectToHost: smtpServer])
157     {
158       if ([client hello]
159           && [client mailFrom: sender])
160         {
161           toErrors = 0;
162           addresses = [recipients objectEnumerator];
163           currentTo = [addresses nextObject];
164           while (currentTo)
165             {
166               if (![client recipientTo: [currentTo pureEMailAddress]])
167                 {
168                   [self logWithFormat: @"error with recipient '%@'", currentTo];
169                   toErrors++;
170                 }
171               currentTo = [addresses nextObject];
172             }
173           if (toErrors == [recipients count])
174             result = [NSException exceptionWithHTTPStatus: 500
175                                   reason: @"cannot send message:"
176                                   @" (smtp) all recipients discarded"];
177           else
178             result = [self _sendMailData: mailData withClient: client
179                            andRejections: toErrors];
180         }
181       else
182         result = [NSException exceptionWithHTTPStatus: 500
183                               reason: @"cannot send message:"
184                               @" (smtp) error when connecting"];
185       [client quit];
186       [client disconnect];
187     }
188
189   return result;
190 }
191
192 - (NSException *) sendMailData: (NSData *) data
193                   toRecipients: (NSArray *) recipients
194                         sender: (NSString *) sender
195 {
196   NSException *result;
197
198   if (![recipients count])
199     result = [NSException exceptionWithHTTPStatus: 500
200                           reason: @"cannot send message: no recipients set"];
201   else
202     {
203       if (![sender length])
204         result = [NSException exceptionWithHTTPStatus: 500
205                               reason: @"cannot send message: no sender set"];
206       else
207         {
208           if ([mailingMechanism isEqualToString: @"sendmail"])
209             result = [self _sendmailSendData: data
210                            toRecipients: recipients
211                            sender: [sender pureEMailAddress]];
212           else
213             result = [self _smtpSendData: data
214                            toRecipients: recipients
215                            sender: [sender pureEMailAddress]];
216         }
217     }
218
219   return result;
220 }
221
222 - (NSException *) sendMimePart: (id <NGMimePart>) part
223                   toRecipients: (NSArray *) recipients
224                         sender: (NSString *) sender
225 {
226   NSData *mailData;
227
228   mailData = [[NGMimePartGenerator mimePartGenerator]
229                generateMimeFromPart: part];
230
231   return [self sendMailData: mailData
232                toRecipients: recipients
233                sender: sender];
234 }
235
236 - (NSException *) sendMailAtPath: (NSString *) filename
237                     toRecipients: (NSArray *) recipients
238                           sender: (NSString *) sender
239 {
240   NSException *result;
241   NSData *mailData;
242
243   mailData = [NSData dataWithContentsOfFile: filename];
244   if ([mailData length] > 0)
245     result = [self sendMailData: mailData
246                    toRecipients: recipients
247                    sender: sender];
248   else
249     result = [NSException exceptionWithHTTPStatus: 500
250                           reason: @"cannot send message: no data"
251                           @" (missing or empty file?)"];
252
253   return nil;
254 }
255
256 @end