sending mail
|
|
Thread rating:  |
Santa Claus - 26 May 2007 00:51 GMT this may not be the proper group to ask in but i'll post the background at least and the problem and maybe one of you folks can help me out or point me in the direction.
there's an order form that the results of the order form goes out via e-mail to all subscribers to the list. the order form is to order in-game shifts (alterations to a character's appearance) and paid by in-game currency, no account information or sensitive information is given other than email address and contact information. The woman that hosts that also has the website that the form is on that sends the email.
a few years ago i tried to duplicate that effort and did so with limited success until my isp told me to shut down my mail server so i did. my form is still online but now doesn't send any mail. it only echos the results to the user telling them to mail that to the list.
now the woman wants to close down her web server and mailing list and she needs a replacement order form. i figured that since mine is still online and ready, i can take over the task but i can't send mails.
is there any way i can tell it to send mail through my mac.com mail server using my authentification?
i currently have it set up in html plus javascript calling a perl cgi executable.
and no, it's not thousands of lines long, it's 321 lines long total for the perl. the html/java, well we won't discuss THAT part
David Phillip Oster - 26 May 2007 05:12 GMT > this may not be the proper group to ask in but i'll post the background > at least and the problem and maybe one of you folks can help me out or [quoted text clipped - 24 lines] > and no, it's not thousands of lines long, it's 321 lines long total for > the perl. the html/java, well we won't discuss THAT part The following is a complete, working, CGI, which when called, sends an email message:
#import <Foundation/Foundation.h> #import <Message/NSMailDelivery.h>
int main (int argc, const char * argv[]) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; if ([NSMailDelivery hasDeliveryClassBeenConfigured]) { [NSMailDelivery deliverMessage:@"This is a two\nline body of a message\n" subject:@"Test Message From David POster" to:@"example@example.com"]; } [pool release]; return 0; }
Don't forget to drag the Message.framework into your project.
Read the comments in NSMailDelivery.h file for more information.
To use this, turn on Personal Web Sharing in your Macintosh, put the compiled code in the appropriate CGI bin directory inside /Library/WebServer
Naturally you'll need to put your Mac on a static IP address.
A real CGI would look at argv and the environment variables.
Santa Claus - 26 May 2007 07:33 GMT > > this may not be the proper group to ask in but i'll post the background > > at least and the problem and maybe one of you folks can help me out or [quoted text clipped - 54 lines] > > A real CGI would look at argv and the environment variables. that works great, unfortunately i can't change the from person in that simple one. i tried to do it the right way but kept getting errors all over the place.
if i can't change the from, i may as well leave it there and use the simple one. it's better than nothing...
i tried the other method this way if ([NSMailDelivery hasDeliveryClassBeenConfigured]) { /* To Reply-To Subject Cc Bcc Date */ NSMutableDictionary *myheaders = [NSMutableDictionary dictionary]; [myheaders setObject: @"test@me.com" forKey: @"To"]; [myheaders setObject: @"santa@northpole.com" forKey: @"From"]; [myheaders setObject: @"santa@northpole.com" forKey: @"Reply-To"]; [myheaders setObject: @"test subject" forKey: @"Subject"]; [NSMailDelivery deliverMessage:@"This is a two\nline body of a message\n" headers:myheaders format:NSASCIIMailFormat protocol:nil]; }
it compiles properly but the console log is telling me some real odd things
2007-05-26 02:29:35.596 echo-cgi[10251] *** -[NSCFString attribute:atIndex:effectiveRange:]: selector not recognized [self = 0xe07c] 2007-05-26 02:29:35.597 echo-cgi[10251] Exception raised during message encoding: *** -[NSCFString attribute:atIndex:effectiveRange:]: selector not recognized [self = 0xe07c]
Sherm Pendley - 26 May 2007 08:39 GMT > i tried the other method this way > if ([NSMailDelivery hasDeliveryClassBeenConfigured]) [quoted text clipped - 29 lines] > encoding: *** -[NSCFString attribute:atIndex:effectiveRange:]: selector > not recognized [self = 0xe07c] It clear as a bell to me - I've *never* sent email with Objective-C, and I found the answer in the 30 seconds it took to google "NSMailDelivery" and look at the declaration of the method you're trying to call:
+ (BOOL)deliverMessage: (NSAttributedString *)messageBody headers: (NSDictionary *)messageHeaders format: (NSString *)messageFormat protocol: (NSString *)deliveryProtocol;
You're passing an NSString to a method that is very clearly documented as expecting an NSAttributedString. The error is another clue - attribute: atIndex:effectiveRange: is documented as being a method in NSAttributedString, and the message shows that it's being sent to an NSCFString instance instead.
sherm--
 Signature Web Hosting by West Virginians, for West Virginians: http://wv-www.net Cocoa programming in Perl: http://camelbones.sourceforge.net
David Phillip Oster - 26 May 2007 16:58 GMT > that works great, unfortunately i can't change the from person in that > simple one. i tried to do it the right way but kept getting errors all > over the place. I'm glad that this looks like its working for you.
It is picking up details of which servers to use from your Mail.app configuration.
I believe the webserver runs as user "www" but since that user already exists, I don't think you can connect to it by making a user named "www" in the Accounts pane of System Preferences.
You can create a new user, log in to that user in Finder, configure its Mail.app account, then the settings will be written to ~/Library/Preferences/com.apple.mail.plist and the mail servers that require passwords will have entries in the login.keychain
You can use the "set effective uid" feature of the Unix "chmod" command to make your CGI executable by the webserver, but run as this second user. This should allow the cgi to send mail using one set of settings while you personaly use a different set.
And it should work, even if no-one is logged in.
but I haven't actually tried any of the above.
I installed the FastCGI apache module in my OS X webserver: http://fastcgi.com/ which lets me write CGIs in Objective-C that are persistent That way, the CGI program stays alive from requerst to request, not running main() and initializing itself on every request.
If you are interested in using FastCGI with the Mac's built-in webserver, ask in comp.sys.mac.programmer.help with an appropriate subject line, and I'll go into detail.
Santa Claus - 29 May 2007 12:44 GMT > > that works great, unfortunately i can't change the from person in that > > simple one. i tried to do it the right way but kept getting errors all [quoted text clipped - 23 lines] > > but I haven't actually tried any of the above. ok, here's what i have so far.
chmod it to 6555 makes it work with web user partly, chmod to 755 doesn't.
755 gives message "no mail server set up" 6555 gives message "message not sent"
under sudo from the terminal it does this
755 gives "no mail server set up" 6555 gives "message sent"
all that is from the uncommented message delivery method, if i leave it commented out, it will not send the message at all.
by the way, why do they use attributed strings when a single string should work?
#import <Foundation/Foundation.h> #include <AppKit/AppKit.h> #import <Message/NSMailDelivery.h>
int main (int argc, const char * argv[]) { printf ("Content-type: text/plain\n\n"); int returnval; NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; if ([NSMailDelivery hasDeliveryClassBeenConfigured]) { /* To Reply-To Subject Cc Bcc Date */ NSMutableDictionary *myheaders = [[[NSMutableDictionary alloc] init] autorelease]; [myheaders setObject: [[NSAttributedString alloc] initWithString: @"ESC_Requests@yahoogroups.com"] forKey: @"To"]; [myheaders setObject: [[NSAttributedString alloc] initWithString: @"ESC_Requests@yahoogroups.com"] forKey: @"From"]; [myheaders setObject: [[NSAttributedString alloc] initWithString: @"ESC_Requests@yahoogroups.com"] forKey: @"Reply-To"]; [myheaders setObject: [[NSAttributedString alloc] initWithString: @"test subject" ] forKey: @"Subject"]; [myheaders setObject: [[NSAttributedString alloc] initWithString: @"" ] forKey: @"Date"]; returnval = [NSMailDelivery deliverMessage:@"This is a two\nline body of a message\n" headers:myheaders format:NSASCIIMailFormat protocol:nil]; //returnval = [NSMailDelivery deliverMessage:@"This is a two\nline body of a message\n" subject:@"Test Message" to:@"ESC_Requests@yahoogroups.com"]; if (returnval) { printf("message sent\n"); } else { printf("message not sent\n"); } } else { printf("no mail server set up\n"); } [pool release]; return returnval; }
David Phillip Oster - 29 May 2007 15:31 GMT > by the way, why do they use attributed strings when a single string > should work? The body is an attributed string so it can colored text, styled text, and, with NSMIMEMailFormat, attachments. The headers are just NSStrings. In your example, you write:
[[NSAttributedString alloc] initWithString: @"ESC_Requests@yahoogroups.com"]
which has two problems: (1) as an attributed string, it leaks. (2) Headers are NSStrings. Use just: @"ESC_Requests@yahoogroups.com"
> all that is from the uncommented message delivery method, if i leave it > commented out, it will not send the message at all. One would not expect commented out code to do anything.
I apologize to you. NSMailDelivery is a nice, simple to use class, but it appears to be too high level to solve your particular problem.
Before posting, I did test that "MailMe" could send an email message when run interactively from the command line.
Now that I actually try to run my test "MailMe" program as a CGI, I see that it wants to access the ~/Library folder of the current user. When I run "MailMe" as a CGI with file access bits 755, [NSMailDelivery hasDeliveryClassBeenConfigured] returns false. seteuid, and [NSMailDelivery deliverMessage:...] returns false, apparently failing to convince the keychain to give it the password of the SMTP server.
In the past, I've written programs that sent mail by opening a TCP/IP connection to the SMTP server and sending it a few lines of text in the correct protocol. At the time, I used the PowerPlant Mail classes, but they came with the source code. For debugging, I've used Telnet to open a connection to the correct host and port number and just typed at it to send mail. I suggest you read http://www.ietf.org/rfc/rfc0821.txt
Santa Claus - 30 May 2007 00:41 GMT > > by the way, why do they use attributed strings when a single string > > should work? [quoted text clipped - 28 lines] > apparently failing to convince the keychain to give it the password of > the SMTP server. i got it. i created a user, created the email account in mail for that user, and set up the program to send mail with that email account. then did a chmod 6755 and then sudo chown the file to the other user. did a su wwwmailuser (the name of the account) and ran it and it asked for the permissions to the keychain once and sent the email. once i figured that out, i found all i really need to do is su to www and then run it in terminal once as www. of course, that requires www's password and i have none so su won't work.
David Phillip Oster - 30 May 2007 02:21 GMT > i got it. i created a user, created the email account in mail for that > user, and set up the program to send mail with that email account. then [quoted text clipped - 4 lines] > in terminal once as www. of course, that requires www's password and i > have none so su won't work. Congratulations!
The man page for su says that
sudo su -l www
should work (give it the admin password)
Michael Ash - 30 May 2007 03:01 GMT > i got it. i created a user, created the email account in mail for that > user, and set up the program to send mail with that email account. then [quoted text clipped - 4 lines] > in terminal once as www. of course, that requires www's password and i > have none so su won't work. But sudo will.
In any case, you inadvertently stumbled onto the correct thing to do. You don't want every single CGI script to be able to read and write these settings, you just want this one script to be able to do it, so running it as a separate user is a good idea anyway.
 Signature Michael Ash Rogue Amoeba Software
Santa Claus - 30 May 2007 11:23 GMT > > i got it. i created a user, created the email account in mail for that > > user, and set up the program to send mail with that email account. then [quoted text clipped - 11 lines] > settings, you just want this one script to be able to do it, so running it > as a separate user is a good idea anyway. blast it, i rebooted the machine to unload the cache (some programs were taking up most of the memory and none of them were mine) and suddenly it stopped working again until i gave access again. it seems it's once per reboot which means that method isn't good enough. i guess i'll have to do it your way <cringe>
|
|
|