Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
Home
Discussion Groups
General
GeneralPortable MacsHardwareNetworking
Applications
Mac ApplicationsEudoraFirefox / MozillaInternet ExplorerOutlook ExpressMS OfficeEntourageExcelPowerPointWordVirtual PCMedia PlayerOther MS Products
Programming
Mac ProgrammingCodeWarriorPerl
Country Specific
Australian Mac GroupUK Mac Group

Mac Forum / Programming / Mac Programming / May 2007



Tip: Looking for answers? Try searching our database.

sending mail

Thread view: 
Enable EMail Alerts  Start New Thread
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>
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.