add delivery notification requests and fix memory leak.

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@31571 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Richard Frith-MacDonald 2010-10-28 22:50:38 +00:00
parent 79eac15152
commit 895a0f38ff
4 changed files with 96 additions and 2 deletions

View file

@ -1,3 +1,10 @@
2010-10-28 Richard Frith-Macdonald <rfm@gnu.org>
* Headers/Additions/GNUstepBase/GSMime.h
* Source/Additions/GSMime.m: Add support for delivery receipts.
* Source/NSURLConnection.m: Fix simple leak in
([+sendSynchronousRequest:returningResponse:error:])
2010-10-27 Richard Frith-Macdonald <rfm@gnu.org>
* Source/GSFFIInvocation.m: Revert David's last change ,which caused

View file

@ -322,6 +322,14 @@ typedef enum {
*/
- (void) send: (GSMimeDocument*)message;
/** Add the message to the queue of emails to be sent by the receiver.<br />
* Also adds an envelope ID string to be used to uniquely identify the
* message for delivery receipting purposes.<br />
* For this to work, the SMTP gateway being used must support the SMTP
* service extension for delivery status notification (RFC 3460).
*/
- (void) send: (GSMimeDocument*)message envelopeID: (NSString*)envid;
/** Set the delegate to receive callback methods indicating when a message
* is sent, failed, or removed from the queue unsent.
*/

View file

@ -67,6 +67,7 @@
NSString *username;\
NSTimer *timer;\
GSMimeDocument *current;\
GSMimeHeader *version;\
NSMutableArray *queue;\
NSMutableArray *pending;\
NSInputStream *istream;\
@ -6151,6 +6152,7 @@ typedef enum {
TP_IDLE,
TP_OPEN,
TP_INTRO,
TP_EHLO,
TP_HELO,
TP_AUTH,
TP_MESG,
@ -6160,6 +6162,10 @@ typedef enum {
TP_BODY
} CState;
typedef enum {
SMTPE_DSN, // delivery status notification extension
} SMTPE;
NSString *
eventText(NSStreamEvent e)
{
@ -6350,6 +6356,20 @@ GS_PRIVATE_INTERNAL(GSMimeSMTPClient)
- (void) send: (GSMimeDocument*)message
{
[self send: message envelopeID: nil];
}
- (void) send: (GSMimeDocument*)message envelopeID: (NSString*)envid
{
if (nil == [message headerNamed: @"mime-version"])
{
[message setHeader: @"MIME-Version" value: @"1.0" parameters: nil];
}
if (nil != envid)
{
[[message headerNamed: @"mime-version"] setObject: envid
forKey: @"ENVID"];
}
[internal->queue addObject: message];
if (internal->cState == TP_IDLE)
{
@ -6407,6 +6427,7 @@ GS_PRIVATE_INTERNAL(GSMimeSMTPClient)
{
case TP_OPEN: return @"waiting for connection to SMTP server";
case TP_INTRO: return @"waiting for initial prompt from SMTP server";
case TP_EHLO: return @"waiting for SMTP server EHLO completion";
case TP_HELO: return @"waiting for SMTP server HELO completion";
case TP_AUTH: return @"waiting for SMTP server AUTH response";
case TP_FROM: return @"waiting for ack of FROM command";
@ -6507,6 +6528,7 @@ GS_PRIVATE_INTERNAL(GSMimeSMTPClient)
NSString *tmp;
internal->current = [internal->queue objectAtIndex: 0];
internal->version = [internal->current headerNamed: @"mime-version"];
if (internal->cState == TP_IDLE)
{
@ -6534,7 +6556,20 @@ GS_PRIVATE_INTERNAL(GSMimeSMTPClient)
[self _identity]];
}
tmp = [NSString stringWithFormat: @"MAIL FROM: %@\r\n", from];
tmp = [internal->version objectForKey: @"ENVID"];
if (nil == tmp)
{
tmp = [NSString stringWithFormat: @"MAIL FROM: <%@>\r\n", from];
}
else
{
/* Tell the mail server we want headers, not the full body
* when an email is bounced or acknowledged.
* Set the envelope ID to be the ID of the current message.
*/
tmp = [NSString stringWithFormat:
@"MAIL FROM: <%@> RET=HDRS ENVID=%@\r\n", from, tmp];
}
NSDebugMLLog(@"GSMime", @"Initiating new mail message - %@", tmp);
internal->cState = TP_FROM;
[self _timer: 20.0];
@ -6543,7 +6578,17 @@ GS_PRIVATE_INTERNAL(GSMimeSMTPClient)
else if (internal->cState == TP_FROM)
{
tmp = [[internal->current headerNamed: @"to"] value];
tmp = [NSString stringWithFormat: @"RCPT TO: <%@>\r\n", tmp];
if (nil == [internal->version objectForKey: @"ENVID"])
{
tmp = [NSString stringWithFormat: @"RCPT TO: <%@>\r\n", tmp];
}
else
{
/* We have an envelope ID, so we need success/failure reports.
*/
tmp = [NSString stringWithFormat:
@"RCPT TO: <%@> NOTIFY=SUCCESS,FAILURE\r\n", tmp];
}
NSDebugMLLog(@"GSMime", @"Destination - %@", tmp);
internal->cState = TP_TO;
[self _timer: 20.0];
@ -6881,6 +6926,39 @@ GS_PRIVATE_INTERNAL(GSMimeSMTPClient)
}
break;
case TP_EHLO:
if (c == 220)
{
NSDebugMLLog(@"GSMime", @"System acknowledged EHLO");
if ([internal->username length] == 0)
{
internal->cState = TP_MESG;
[self _doMessage];
}
else
{
NSString *tmp;
tmp = [NSString stringWithFormat: @"AUTH PLAIN %@\r\n",
[GSMimeDocument encodeBase64String: internal->username]];
NSDebugMLLog(@"GSMime", @"Ehlo OK - sending auth");
internal->cState = TP_AUTH;
[self _timer: 30.0];
[self _sendData: [tmp dataUsingEncoding: NSUTF8StringEncoding]];
}
}
else
{
NSString *tmp;
tmp = [NSString stringWithFormat: @"HELO %@\r\n", [self _identity]];
NSDebugMLLog(@"GSMime", @"Ehlo failed - sending helo");
internal->cState = TP_HELO;
[self _timer: 30.0];
[self _sendData: [tmp dataUsingEncoding: NSUTF8StringEncoding]];
}
break;
case TP_HELO:
if (c == 250)
{

View file

@ -342,6 +342,7 @@ typedef struct
RELEASE(limit);
}
data = RETAIN([collector _data]);
[conn release];
}
return AUTORELEASE(data);
}