/* 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