diff --git a/ChangeLog b/ChangeLog index 39ef06ede..1fdc36ba7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2007-08-09 Wolfgang Sourdeau + + * SoObjects/SOGo/SOGoMailer.m: new abstraction class module that + provides a common API for sending emails, no matter what the + transport is. + 2007-08-08 Wolfgang Sourdeau * UI/MailerUI/UIxMailFolderActions.m ([UIxMailFolderActions diff --git a/SoObjects/SOGo/SOGoMailer.h b/SoObjects/SOGo/SOGoMailer.h new file mode 100644 index 000000000..29a4c6fca --- /dev/null +++ b/SoObjects/SOGo/SOGoMailer.h @@ -0,0 +1,50 @@ +/* SOGoMailer.h - this file is part of SOGo + * + * Copyright (C) 2007 Inverse groupe conseil + * + * Author: Wolfgang Sourdeau + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef SOGOMAILER_H +#define SOGOMAILER_H + +@class NSArray; +@class NSException; +@class NSString; + +@protocol NGMimePart; + +@interface SOGoMailer : NSObject +{ + NSString *mailingMechanism; + NSString *smtpServer; +} + ++ (id) sharedMailer; + +- (NSException *) sendMailAtPath: (NSString *) filename + toRecipients: (NSArray *) recipients + sender: (NSString *) sender; + +- (NSException *) sendMimePart: (id ) part + toRecipients: (NSArray *) recipients + sender: (NSString *) sender; + +@end + +#endif /* SOGOMAILER_H */ diff --git a/SoObjects/SOGo/SOGoMailer.m b/SoObjects/SOGo/SOGoMailer.m new file mode 100644 index 000000000..7ea6490bb --- /dev/null +++ b/SoObjects/SOGo/SOGoMailer.m @@ -0,0 +1,256 @@ +/* SOGoMailer.m - this file is part of SOGo + * + * Copyright (C) 2007 Inverse groupe conseil + * + * Author: Wolfgang Sourdeau + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#import +#import +#import +#import +#import + +#import +#import +#import +#import +#import + +#import "NSString+Utilities.h" +#import "SOGoMailer.h" + +#define defaultMailingMechanism @"sendmail" +#define defaultSMTPServer @"localhost" + +@implementation SOGoMailer + ++ (id) sharedMailer +{ + static id sharedMailer = nil; + + if (!sharedMailer) + sharedMailer = [self new]; + + return sharedMailer; +} + +- (id) init +{ + NSUserDefaults *ud; + + if ((self = [super init])) + { + ud = [NSUserDefaults standardUserDefaults]; + mailingMechanism = [ud stringForKey: @"SOGoMailingMechanism"]; + if (mailingMechanism) + { + if (!([mailingMechanism isEqualToString: @"sendmail"] + || [mailingMechanism isEqualToString: @"smtp"])) + { + [self logWithFormat: @"mechanism '%@' is invalid and" + @" should be set to 'sendmail' or 'smtp' instead", + mailingMechanism]; + [self logWithFormat: @"falling back to default '%@' mechanism", + defaultMailingMechanism]; + mailingMechanism = defaultMailingMechanism; + } + } + else + { + [self logWithFormat: @"default mailing mechanism set to '%@'", + defaultMailingMechanism]; + mailingMechanism = defaultMailingMechanism; + } + [mailingMechanism retain]; + + if ([mailingMechanism isEqualToString: @"smtp"]) + { + smtpServer = [ud stringForKey: @"SOGoSMTPServer"]; + if (!smtpServer) + { + [self logWithFormat: @"default smtp server set to '%@'", + defaultSMTPServer]; + smtpServer = defaultSMTPServer; + } + [smtpServer retain]; + } + else + smtpServer = nil; + } + + return self; +} + +- (void) dealloc +{ + [mailingMechanism release]; + [smtpServer release]; + [super dealloc]; +} + +- (NSException *) _sendmailSendData: (NSData *) mailData + toRecipients: (NSArray *) recipients + sender: (NSString *) sender +{ + NSException *result; + NGSendMail *mailer; + + mailer = [NGSendMail sharedSendMail]; + if ([mailer isSendMailAvailable]) + result = [mailer sendMailData: mailData + toRecipients: recipients + sender: sender]; + else + result = [NSException exceptionWithHTTPStatus: 500 + reason: @"cannot send message:" + @" no sendmail binary!"]; + + return result; +} + +- (NSException *) _sendMailData: (NSData *) mailData + withClient: (NGSmtpClient *) client + andRejections: (unsigned int) toErrors +{ + NSException *result; + + if (toErrors > 0) + [self logWithFormat: @"sending email despite address rejections"]; + if ([client sendData: mailData]) + result = nil; + else + result = [NSException exceptionWithHTTPStatus: 500 + reason: @"cannot send message:" + @" (smtp) failure when sending data"]; + + return result; +} + +- (NSException *) _smtpSendData: (NSData *) mailData + toRecipients: (NSArray *) recipients + sender: (NSString *) sender +{ + NGSmtpClient *client; + NSEnumerator *addresses; + NSString *currentTo; + unsigned int toErrors; + NSException *result; + + client = [NGSmtpClient smtpClient]; + if ([client connectToHost: smtpServer]) + { + if ([client hello] + && [client mailFrom: sender]) + { + toErrors = 0; + addresses = [recipients objectEnumerator]; + currentTo = [addresses nextObject]; + while (currentTo) + { + if (![client recipientTo: [currentTo pureEMailAddress]]) + { + [self logWithFormat: @"error with recipient '%@'", currentTo]; + toErrors++; + } + currentTo = [addresses nextObject]; + } + if (toErrors == [recipients count]) + result = [NSException exceptionWithHTTPStatus: 500 + reason: @"cannot send message:" + @" (smtp) all recipients discarded"]; + else + result = [self _sendMailData: mailData withClient: client + andRejections: toErrors]; + } + else + result = [NSException exceptionWithHTTPStatus: 500 + reason: @"cannot send message:" + @" (smtp) error when connecting"]; + [client quit]; + [client disconnect]; + } + + return result; +} + +- (NSException *) sendMailData: (NSData *) data + toRecipients: (NSArray *) recipients + sender: (NSString *) sender +{ + NSException *result; + + if (![recipients count]) + result = [NSException exceptionWithHTTPStatus: 500 + reason: @"cannot send message: no recipients set"]; + else + { + if (![sender length]) + result = [NSException exceptionWithHTTPStatus: 500 + reason: @"cannot send message: no sender set"]; + else + { + if ([mailingMechanism isEqualToString: @"sendmail"]) + result = [self _sendmailSendData: data + toRecipients: recipients + sender: [sender pureEMailAddress]]; + else + result = [self _smtpSendData: data + toRecipients: recipients + sender: [sender pureEMailAddress]]; + } + } + + return result; +} + +- (NSException *) sendMimePart: (id ) part + toRecipients: (NSArray *) recipients + sender: (NSString *) sender +{ + NSData *mailData; + + mailData = [[NGMimePartGenerator mimePartGenerator] + generateMimeFromPart: part]; + + return [self sendMailData: mailData + toRecipients: recipients + sender: sender]; +} + +- (NSException *) sendMailAtPath: (NSString *) filename + toRecipients: (NSArray *) recipients + sender: (NSString *) sender +{ + NSException *result; + NSData *mailData; + + mailData = [NSData dataWithContentsOfFile: filename]; + if ([mailData length] > 0) + result = [self sendMailData: mailData + toRecipients: recipients + sender: sender]; + else + result = [NSException exceptionWithHTTPStatus: 500 + reason: @"cannot send message: no data" + @" (missing or empty file?)"]; + + return nil; +} + +@end