RSS

How to Send an Email in Cocoa

There are a few ways to send email from a Cocoa app. A few frameworks let you directly send an email without the user ever having to do anything. In my development, I wanted to open Mail with a pre-constructed message and let the user edit the email in Mail before sending it. I had to make two tries at this to get it to work properly.

Initial Try

I originally used a mailto: link to open Mail. The code looks something like this:

1
2
3
4
5
6
NSString *encodedSubject = [NSString stringWithFormat:@"SUBJECT=%@", [subject stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
NSString *encodedBody = [NSString stringWithFormat:@"BODY=%@", [body stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
NSString *encodedTo = [to stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSString *encodedURLString = [NSString stringWithFormat:@"mailto:%@?%@&%@", encodedTo, encodedSubject, encodedBody];
NSURL *mailtoURL = [NSURL URLWithString:encodedURLString];
[[NSWorkspace sharedWorkspace] openURL:mailtoURL];

The above code is really simple. Essentially you take three strings subject, body, and to and escape them. You then formulate a mailto: url and open it. This is a very simple and clean approach, and I like it much more than what I ended up having to do.

The Problem

The issue here actually lies not with Cocoa. I can’t find an knowledgeable source stating an exact number, but there appears to be some character limit at which Mail messages get cut off. This was unacceptable for me because I need to include long body messages. Instead, I turned to AppleScript.

The Solution

I made a quick AppleScript that sends an email:

1
2
3
4
tell application "Mail"
	make new outgoing message with properties {visible:true, subject:"a", content:"b"}
	activate
end tell

Moving it into Cocoa, I have:

1
2
3
4
5
NSAppleScript *mailScript;
NSString *scriptString= [NSString stringWithFormat:@"tell application \"Mail\"\nmake new outgoing message with properties {visible:true, subject:\"%@\", content:\"%@\"}\nactivate\nend tell",subject,body];
mailScript = [[NSAppleScript alloc] initWithSource:scriptString];
[mailScript executeAndReturnError:nil];
[mailScript release];

The script is quite simple. I tells Mail to make a new message and fill in the message with our given properties. It then tells Mail to activate so the email becomes the main, key window. You might want to change this if you don’t want your application to lose focus when a user opts to send an email.

There is a small little bug that creeps its way in to this. Have you found it? If you have a subject or body string that contains a quote (“), then that will cause AppleScript to fail. To fix this just add a line like this above the previous code:

1
[body replaceOccurrencesOfString:@"\"" withString:@"\\\"" options:0 range:NSMakeRange(0, [body length])];

That should do it. You should be able to launch a new Mail window with fields already populated. You can look through the AppleScript dictionary to find other properties you can set like who the email goes to and more. If you have any comments or other ways to do this, please feel free to comment below.

  • gargantuan
    LSGetApplicationForURL should return the users default mail app, which would let you add support for different email clients.
  • dev
    Thanks for this info. But it doesn't seem to work with HTML tags in the body. The HTML is not formatted as intended, just goes in as plain text :(
  • AnnieWH
    The second way has to tell the appointed mail app. But I want to open the default mail app. I also need a pre-constructed message, so the first does not work.
    I have searched for a long time. But I didn't find out how to detect which email client is the user's default.
  • jfid
    Hi,

    the first try works perfect (of course) if you don't need a pre-constructed message. Besides, it opens your default mail app, not necessarily Mail app.

    It has been very useful for me
blog comments powered by Disqus
« Who’s Using the Nib? | Moved to MediaTemple »