Commits

Peter Hosey  committed 4ac369b

Fix MailMe being disabled for “incompatibility” (i.e., not instantiating) when the user has not set up any accounts.

We now load the accounts on demand, and throw away the cached default-account dictionary whenever Mail quits (in case the user changed the accounts).

Includes a minor change in memory management of one local variable (destAddress), which would otherwise have become a leak, and a fix (by conditionalizing a break statement) for the account scan stopping on the first account it finds an SMTP account for, even if the scan rejects the account for missing or invalid data.

Fixes #73.

  • Participants
  • Parent commits 07b66c6
  • Branches default

Comments (0)

Files changed (1)

File Plugins/Displays/MailMe/GrowlMailMeDisplay.m

 	@"-- in response to a Growl notification --\r\n"\
 	@"-- http://growl.info/ --\r\n"
 
+#define MAIL_BUNDLE_IDENTIFIER @"com.apple.mail"
+
 @interface GrowlMailMeDisplay ()
 
-//Intended to be called from -init.
-- (BOOL) gatherAccountsFromMail;
+- (NSDictionary *) defaultSMTPAccountFromMail;
+- (void) workspaceDidTerminateApplication:(NSNotification *)notification;
 
 @end
 
 	if ((self = [super init])) {
 		pathToMailSenderProgram = [[[NSBundle bundleForClass:[self class]] pathForResource:@"simple-mailer" ofType:@"py"] copy];
 
-		if (![self gatherAccountsFromMail])
-			goto fail;
+		NSWorkspace *wksp = [NSWorkspace sharedWorkspace];
+		[[wksp notificationCenter] addObserver:self
+									  selector:@selector(workspaceDidTerminateApplication:)
+										  name:NSWorkspaceDidTerminateApplicationNotification
+										object:wksp];
 
 		tasks = [[NSMutableArray alloc] init];
 	}
 	return self;
-
-fail:
-	[self release];
-	return nil;
 }
 
 - (void) dealloc {
 - (void) displayNotification:(GrowlApplicationNotification *)notification {
 	NSString *destAddress = nil;
 	READ_GROWL_PREF_VALUE(destAddressKey, @"com.Growl.MailMe", NSString *, &destAddress);
+	[NSMakeCollectable(destAddress) autorelease];
 	NSDictionary *noteDict = [notification dictionaryRepresentation];
 
 	if (destAddress) {
-		CFMakeCollectable(destAddress);
 		if([destAddress length]) {
 			NSString *title = [noteDict objectForKey:GROWL_NOTIFICATION_TITLE];
 			NSString *desc = [noteDict objectForKey:GROWL_NOTIFICATION_DESCRIPTION];
 			//One solution would be an easy way to attach at least one file in the simple-mailer program. Another would be a way to create a MIME multi-part message and to have simple-mailer handle it correctly.
 			//	NSData *imageData = [noteDict objectForKey:GROWL_NOTIFICATION_ICON];
 
+			if (!defaultSMTPAccount) {
+				defaultSMTPAccount = [[self defaultSMTPAccountFromMail] retain];
+				if (!defaultSMTPAccount) {
+					//We can't do anything without an account.
+					NSLog(@"MailMe: No suitable SMTP account found");
+					return;
+				}
+			}
+
 			BOOL useTLS = [[defaultSMTPAccount objectForKey:@"SSLEnabled"] boolValue];
 			NSString *username = [defaultSMTPAccount objectForKey:@"Username"];
 			NSString *hostname = [defaultSMTPAccount objectForKey:@"Hostname"];
 	} else {
 		NSLog(@"(MailMe) WARNING: No destination address set");
 	}
-	[destAddress release];
 
 	id clickContext = [noteDict objectForKey:GROWL_NOTIFICATION_CLICK_CONTEXT];
 	if (clickContext) {
 	return NO;
 }
 
-- (BOOL) gatherAccountsFromMail {
+- (NSDictionary *) defaultSMTPAccountFromMail {
+	NSDictionary *viableAccount = nil;
+
 	NSArray *deliveryAccounts = [NSMakeCollectable(CFPreferencesCopyAppValue(CFSTR("DeliveryAccounts"), CFSTR("com.apple.Mail"))) autorelease];
 	if (!deliveryAccounts)
-		return NO;
+		return viableAccount;
 
 	NSArray *mailAccounts = [NSMakeCollectable(CFPreferencesCopyAppValue(CFSTR("MailAccounts"), CFSTR("com.apple.Mail"))) autorelease];
 	if (!mailAccounts)
-		return NO;
+		return viableAccount;
 
 	NSMutableDictionary *deliveryAccountsBySMTPIdentifier = [NSMutableDictionary dictionaryWithCapacity:[deliveryAccounts count]];
 	for (NSDictionary *account in deliveryAccounts) {
 		if (!identifier)
 			continue;
 
-		defaultSMTPAccount = [[deliveryAccountsBySMTPIdentifier objectForKey:identifier] copy];
-		if (defaultSMTPAccount) {
+		viableAccount = [deliveryAccountsBySMTPIdentifier objectForKey:identifier];
+		if (viableAccount) {
 			NSString *bareAddress = [[account objectForKey:@"EmailAddresses"] objectAtIndex:0UL];
 			NSString *name = [account objectForKey:@"FullUserName"];
 			fromAddress = [(name ? [NSString stringWithFormat:@"%@ <%@>", name, bareAddress] : bareAddress) copy];
 			if (!fromAddress) {
-				[defaultSMTPAccount release];
-				defaultSMTPAccount = nil;
+				viableAccount = nil;
 			}
 
-			NSNumber *portNumber = [defaultSMTPAccount objectForKey:@"PortNumber"];
+			NSNumber *portNumber = [viableAccount objectForKey:@"PortNumber"];
 			if (portNumber) {
 				NSInteger port = [portNumber integerValue];
 				if (port <= 0 || port > 0xFFFF) {
-					[defaultSMTPAccount release];
-					defaultSMTPAccount = nil;
+					viableAccount = nil;
 				}
 			}
 
-			break;
+			if (viableAccount) {
+				break;
+			}
 		}
 	}
 
-	if (!defaultSMTPAccount) {
-		NSLog(@"MailMe: No suitable SMTP account found");
-		return NO;
+	return viableAccount;
+}
+
+- (void) workspaceDidTerminateApplication:(NSNotification *)notification {
+	NSString *bundleID = [[notification userInfo] objectForKey:@"NSApplicationBundleIdentifier"];
+	if ([bundleID isEqualToString:MAIL_BUNDLE_IDENTIFIER]) {
+		//Clear out our knowledge of the default Mail account, in case it's changed.
+		[defaultSMTPAccount release];
+		defaultSMTPAccount = nil;
 	}
-
-	return YES;
 }
 
 @end