--- parser3/src/classes/mail.C 2002/06/24 11:59:31 1.67 +++ parser3/src/classes/mail.C 2002/08/13 15:55:41 1.78 @@ -3,10 +3,10 @@ Copyright (c) 2001, 2002 ArtLebedev Group (http://www.artlebedev.com) Author: Alexandr Petrosian (http://paf.design.ru) - - $Id: mail.C,v 1.67 2002/06/24 11:59:31 paf Exp $ */ +static const char* IDENT_MAIL_C="$Date: 2002/08/13 15:55:41 $"; + #include "pa_config_includes.h" #include "pa_common.h" @@ -42,6 +42,7 @@ public: MMail(Pool& pool); public: // Methoded bool used_directly() { return false; } + void configure_user(Request& r); private: String mail_name; }; @@ -96,29 +97,34 @@ struct Mail_info { Charset *charset; const char *content_charset_name; String *header; const String **from, **to; + const String *errors_to; }; #endif -static void add_header_attribute(const Hash::Key& aattribute, Hash::Val *ameaning, - void *info) { - Value& lmeaning=*static_cast(ameaning); +const String& extractEmail(const String& string); +static void add_header_attribute(const Hash::Key& raw_element_name, Hash::Val *aelement_value, + void *info) { + Value& element_value=*static_cast(aelement_value); + const String& low_element_name=raw_element_name.change_case(raw_element_name.pool(), String::CC_LOWER); Mail_info& mi=*static_cast(info); // exclude one attribute [body] - if(aattribute==BODY_NAME - || aattribute==CHARSET_NAME) + if(low_element_name==BODY_NAME + || low_element_name==CHARSET_NAME) return; // fetch from & to from header for SMTP - if(mi.from && aattribute=="from") - *mi.from=&lmeaning.as_string(); - if(mi.to && aattribute=="to") - *mi.to=&lmeaning.as_string(); + if(mi.from && low_element_name=="from") + *mi.from=&extractEmail(element_value.as_string()); + if(mi.to && low_element_name=="to") + *mi.to=&extractEmail(element_value.as_string()); + if(low_element_name=="errors-to") + mi.errors_to=&extractEmail(element_value.as_string()); // append header line *mi.header << - aattribute << ":" << - attributed_meaning_to_string(lmeaning, String::UL_MAIL_HEADER). + low_element_name << ":" << + attributed_meaning_to_string(element_value, String::UL_MAIL_HEADER). cstr(String::UL_UNSPECIFIED, 0, mi.charset, mi.content_charset_name) << "\n"; } @@ -190,6 +196,8 @@ static const String& message_hash_to_str from, to }; message_hash.for_each(add_header_attribute, &mail_info); + if(!mail_info.errors_to) + result << "errors-to: postmaster\n"; // errors-to: default if(Value *body_element=static_cast(message_hash.get(*body_name))) { if(Hash *body_hash=body_element->get_hash(&method_name)) { @@ -241,8 +249,8 @@ static const String& message_hash_to_str "\n"; // header|body separator const String& body=body_element->as_string(); - const void *body_ptr=body.cstr(); // body - size_t body_size=body.size(); // body + const char *body_ptr=body.cstr(String::UL_UNSPECIFIED); // body + size_t body_size=strlen(body_ptr); // body const void *mail_ptr; size_t mail_size; Charset::transcode(pool, @@ -263,18 +271,19 @@ static void sendmail(Request& r, const S const String *from, const String *to) { Pool& pool=r.pool(); - char *message_cstr=message.cstr(); + char *message_cstr=message.cstr(String::UL_UNSPECIFIED); Hash *mail_conf=static_cast(r.classes_conf.get(mail_base_class->name())); -#ifdef _MSC_VER + const char *exception_type="email.format"; if(!from) - throw Exception("parser.runtime", + throw Exception(exception_type, &method_name, - "has no 'from' header specified"); + "parameter does not specify 'from' header field"); if(!to) - throw Exception("parser.runtime", + throw Exception(exception_type, &method_name, - "has no 'to' header specified"); + "parameter does not specify 'to' header field"); +#ifdef _MSC_VER SMTP& smtp=*new(pool) SMTP(pool, method_name); Value *server_port; @@ -294,8 +303,8 @@ static void sendmail(Request& r, const S "$"MAIN_CLASS_NAME":"MAIL_NAME".SMTP not defined"); #else // unix - // $MAIN:MAIL.sendmail["/usr/sbin/sendmail -t"] default - // $MAIN:MAIL.sendmail["/usr/lib/sendmail -t"] default + // $MAIN:MAIL.sendmail["/usr/sbin/sendmail -t -i -f postmaster"] default + // $MAIN:MAIL.sendmail["/usr/lib/sendmail -t -i -f postmaster"] default const String *sendmail_command; #ifdef PA_FORCED_SENDMAIL @@ -314,12 +323,21 @@ static void sendmail(Request& r, const S String *test=new(pool) String(pool, "/usr/sbin/sendmail"); if(!file_executable(*test)) test=new(pool) String(pool, "/usr/lib/sendmail"); - test->APPEND_CONST(" -ti"); + test->APPEND_CONST(" -t -i -f postmaster"); sendmail_command=test; } #endif - // we know sendmail_command here + // we know sendmail_command here, should replace "postmaster" with "$from" from message + int at_postmaster=sendmail_command->pos("postmaster"); + if(at_postmaster>0) { + String& reconstructed=sendmail_command->mid(0, at_postmaster); + reconstructed << *from; + reconstructed << sendmail_command->mid(at_postmaster+10/*postmaster*/, sendmail_command->size()); + sendmail_command=&reconstructed; + } + + // execute it Array argv(pool); const String *file_spec; int after_file_spec=sendmail_command->pos(" ", 1); @@ -332,13 +350,13 @@ static void sendmail(Request& r, const S } if(!file_executable(*file_spec)) - throw Exception(0, + throw Exception("email.send", file_spec, "is not executable." #ifdef PA_FORCED_SENDMAIL " Use configure key \"--with-sendmail=appropriate sendmail command\"" #else - " Set $"MAIN_CLASS_NAME":"MAIL_NAME".%s with appropriate sendmail command", + " Set $"MAIN_CLASS_NAME":"MAIL_NAME".%s to appropriate sendmail command", sendmailkey_cstr #endif ); @@ -357,7 +375,7 @@ static void sendmail(Request& r, const S &argv, in, out, err); if(exit_status || err.size()) - throw Exception(0, + throw Exception("email.send", &method_name, "'%s' reported problem: %s (%d)", file_spec->cstr(), @@ -397,6 +415,20 @@ MMail::MMail(Pool& apool) : Methoded(apo add_native_method("send", Method::CT_STATIC, _send, 1, 1); } +void MMail::configure_user(Request& r) { + Pool& pool=r.pool(); + + // $MAIN:MAIL[$SMTP[mail.design.ru]] + if(Value *mail_element=r.main_class->get_element(mail_name, r.main_class, false)) + if(Hash *mail_conf=mail_element->get_hash(0)) + r.classes_conf.put(name(), mail_conf); + else + if( !mail_element->is_string() ) + throw Exception("parser.runtime", + 0, + "$" MAIL_CLASS_NAME ":" MAIL_NAME " is not hash"); +} + // creator Methoded *MMail_create(Pool& pool) {