diff --git a/harbour/ChangeLog b/harbour/ChangeLog index 3a9947a78a..dd856e4d52 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -17,6 +17,33 @@ past entries belonging to author(s): Viktor Szakats. */ +2009-10-16 13:54 UTC+0200 Viktor Szakats (harbour.01 syenar.hu) + * contrib/hbtip/sendmail.prg + * contrib/hbtip/mail.prg + ! Fixed encoding of subject, from, to, cc, bcc address lists, in some + places it was missing (cc, bcc, from), in some other places multiple + address support was missing (to, cc, bcc) from recent addition of + encoding support. + + Added/Fixed support for human readable name component in e-mail addresses. + + Using TIPMAIL:SETHEADER() in HB_SENDMAIL() to set above header components. + ! Several minor cleanups in TIPMAIL:SETHEADER(): + - handling of empty values + - using space instead of tab when passing multiple addresses in headers. + Haven't checked the standard, but I used to see space there. + - Minor formatting, optimizations. + ! Minor tweaks to space and _ char in Q encoding. Now + they are both simply encoded. + ; Overall probably a rewrite would be the best in case of hbtip mailing, + and maybe not just for mailing. Code is full of strange tweaks, + redundancy and the class layout/communication is rather strange, f.e. + SMTP protocol data is passed via TURL:cFile variable from HB_SENDMAIL + to SMTP client class. Also charset support is just an aftertought so + user code needs close syncronisation with HB_SENDMAIL() and replicating + the same parameter parsing logic on multiple layers of code. + And I've probably just scratched the surface, f.e. I didn't test + attachments of HTML mails and probably several other options as well. + ; Anyway please test. + 2009-10-15 18:43 UTC-0800 Pritpal Bedi (pritpal@vouchcac.com) * contrib/hbqt/generator/hbqtgen.prg ! Changes to implemented GC pointers. diff --git a/harbour/contrib/hbtip/mail.prg b/harbour/contrib/hbtip/mail.prg index 18b6ab907f..471cb34955 100644 --- a/harbour/contrib/hbtip/mail.prg +++ b/harbour/contrib/hbtip/mail.prg @@ -313,13 +313,13 @@ METHOD ToString() CLASS TipMail cRet += "Date: " + ::hHeaders[ "Date" ] + e"\r\n" ENDIF IF "From" $ ::hHeaders - cRet += "From: " + LTrim( WordEncodeQ( tip_GetNameEMail( ::hHeaders[ "From" ] ), ::cCharset ) + " <" + tip_GetRawEMail( ::hHeaders[ "From" ] ) + ">" ) + e"\r\n" + cRet += "From: " + ::hHeaders[ "From" ] + e"\r\n" ENDIF IF "To" $ ::hHeaders - cRet += "To: " + LTrim( WordEncodeQ( tip_GetNameEMail( ::hHeaders[ "To" ] ), ::cCharset ) + " <" + tip_GetRawEMail( ::hHeaders[ "To" ] ) + ">" ) + e"\r\n" + cRet += "To: " + ::hHeaders[ "To" ] + e"\r\n" ENDIF IF "Subject" $ ::hHeaders - cRet += "Subject: " + WordEncodeQ( ::hHeaders[ "Subject" ], ::cCharset ) + e"\r\n" + cRet += "Subject: " + ::hHeaders[ "Subject" ] + e"\r\n" ENDIF IF Len( ::aAttachments ) > 0 cRet += "Mime-Version:" + ::hHeaders[ "Mime-Version" ] + e"\r\n" @@ -513,8 +513,9 @@ METHOD MakeBoundary() CLASS TipMail RETURN cBound -METHOD setHeader( cSubject, cFrom, cTo, cCC, cBCC ) CLASS TipMail +METHOD setHeader( cSubject, cFrom, xTo, xCC, xBCC ) CLASS TipMail LOCAL aTo, aCC, aBCC, i, imax + LOCAL cTo, cCC, cBCC IF ! ISCHARACTER( cSubject ) cSubject := "" @@ -524,66 +525,79 @@ METHOD setHeader( cSubject, cFrom, cTo, cCC, cBCC ) CLASS TipMail RETURN .F. ENDIF - IF ISCHARACTER( cTo ) - aTo := { cTo } - ELSEIF ISARRAY( cTo ) - aTo := cTo + IF ISCHARACTER( xTo ) + aTo := { xTo } + ELSEIF ISARRAY( xTo ) + aTo := xTo ENDIF - IF ISCHARACTER( cCC ) - aCC := { cCC } - ELSEIF ISARRAY( cCC ) - aCC := cCC - ENDIF - - IF ISCHARACTER( cBCC ) - aBCC := { cBCC } - ELSEIF ISARRAY( cBCC ) - aBCC := cBCC - ENDIF - - IF aTO == NIL + IF Empty( aTO ) RETURN .F. ENDIF - IF ! ::setFieldPart( "Subject", cSubject ) + IF ISCHARACTER( xCC ) + aCC := { xCC } + ELSEIF ISARRAY( xCC ) + aCC := xCC + ENDIF + + IF ISCHARACTER( xBCC ) + aBCC := { xBCC } + ELSEIF ISARRAY( xBCC ) + aBCC := xBCC + ENDIF + + IF ! ::setFieldPart( "Subject", WordEncodeQ( cSubject, ::cCharset ) ) + RETURN .F. + ENDIF + + IF ! ::setFieldPart( "From", LTrim( WordEncodeQ( tip_GetNameEMail( AllTrim( cFrom ) ), ::cCharset ) + " <" + tip_GetRawEMail( AllTrim( cFrom ) ) + ">" ) ) RETURN .F. ENDIF - IF ! ::setFieldPart( "From", cFrom ) - RETURN .F. - ENDIF - - cTo := aTO[ 1 ] + cTo := "" imax := Len( aTO ) - FOR i := 2 TO imax - cTo += "," + hb_inetCrlf() + Chr( 9 ) + aTo[ i ] + FOR i := 1 TO imax + IF i > 1 + cTo += "," + hb_inetCrlf() + " " + ENDIF + cTo += LTrim( WordEncodeQ( tip_GetNameEMail( AllTrim( aTo[ i ] ) ), ::cCharset ) + " <" + tip_GetRawEMail( AllTrim( aTo[ i ] ) ) + ">" ) NEXT + IF Empty( cTo ) + RETURN .F. + ENDIF + IF ! ::setFieldPart( "To", cTo ) RETURN .F. ENDIF - IF aCC != NIL - cCC := aCC[ 1 ] + IF ! Empty( aCC ) + cCC := "" imax := Len( aCC ) FOR i := 2 TO imax - cCC += "," + hb_inetCrlf() + Chr( 9 ) + aCC[ i ] + IF i > 1 + cCC += "," + hb_inetCrlf() + " " + ENDIF + cCC += LTrim( WordEncodeQ( tip_GetNameEMail( AllTrim( aCC[ i ] ) ), ::cCharset ) + " <" + tip_GetRawEMail( AllTrim( aCC[ i ] ) ) + ">" ) NEXT - IF ! ::setFieldPart( "Cc", cCC ) + IF ! Empty( cCC ) .AND. ! ::setFieldPart( "Cc", cCC ) RETURN .F. ENDIF ENDIF - IF aBCC != NIL - cBCC := aBCC[ 1 ] + IF ! Empty( aBCC ) + cBCC := "" imax := Len( aBCC ) FOR i := 2 TO imax - cBCC += "," + hb_inetCrlf() + Chr( 9 ) + aBCC[ i ] + IF i > 1 + cBCC += "," + hb_inetCrlf() + " " + ENDIF + cBCC += LTrim( WordEncodeQ( tip_GetNameEMail( AllTrim( aBCC[ i ] ) ), ::cCharset ) + " <" + tip_GetRawEMail( AllTrim( aBCC[ i ] ) ) + ">" ) NEXT - IF ! ::setFieldPart( "Bcc", cBCC ) + IF ! Empty( cBCC ) .AND. ! ::setFieldPart( "Bcc", cBCC ) RETURN .F. ENDIF ENDIF @@ -678,11 +692,8 @@ STATIC FUNCTION WordEncodeQ( cData, cCharset ) cString := "=?" + cCharset + "?" + "Q" + "?" FOR EACH c IN cData - IF c == " " - cString += "_" - nLineLen += 1 - ELSEIF Asc( c ) > 126 .OR. ; - c $ '=?!"#$@[\]^`{|}~' .OR. ; + IF Asc( c ) > 126 .OR. ; + c $ '=?!"#$@[\]^`{|}~_' .OR. ; Asc( c ) <= 32 cString += "=" + hb_NumToHex( Asc( c ), 2 ) nLineLen += 3 diff --git a/harbour/contrib/hbtip/sendmail.prg b/harbour/contrib/hbtip/sendmail.prg index fb3022b976..f2b03a1ef6 100644 --- a/harbour/contrib/hbtip/sendmail.prg +++ b/harbour/contrib/hbtip/sendmail.prg @@ -55,14 +55,14 @@ #translate ( LIKE ) => ( hb_regexLike( (), () ) ) -FUNCTION hb_SendMail( cServer, nPort, cFrom, aTo, aCC, aBCC, cBody, cSubject, aFiles, cUser, cPass, cPopServer, nPriority, lRead, bTrace, lPopAuth, lNoAuth, nTimeOut, cReplyTo, lTLS, cSMTPPass, cCharset, cEncoding ) +FUNCTION hb_SendMail( cServer, nPort, cFrom, xTo, xCC, xBCC, cBody, cSubject, aFiles, cUser, cPass, cPopServer, nPriority, lRead, bTrace, lPopAuth, lNoAuth, nTimeOut, cReplyTo, lTLS, cSMTPPass, cCharset, cEncoding ) /* cServer -> Required. IP or domain name of the mail server nPort -> Optional. Port used my email server cFrom -> Required. Email address of the sender - aTo -> Required. Character string or array of email addresses to send the email to - aCC -> Optional. Character string or array of email adresses for CC (Carbon Copy) - aBCC -> Optional. Character string or array of email adresses for BCC (Blind Carbon Copy) + xTo -> Required. Character string or array of email addresses to send the email to + xCC -> Optional. Character string or array of email adresses for CC (Carbon Copy) + xBCC -> Optional. Character string or array of email adresses for BCC (Blind Carbon Copy) cBody -> Optional. The body message of the email as text, or the filename of the HTML message to send. cSubject -> Optional. Subject of the sending email aFiles -> Optional. Array of attachments to the email to send @@ -79,8 +79,18 @@ FUNCTION hb_SendMail( cServer, nPort, cFrom, aTo, aCC, aBCC, cBody, cSubject, aF cReplyTo -> Optional. */ - LOCAL oInMail, cBodyTemp, oUrl, oMail, oAttach, aThisFile, cMimeText,; - cFile, cFname, cFext, cData, oUrl1 + LOCAL oInMail + LOCAL cBodyTemp + LOCAL oUrl + LOCAL oMail + LOCAL oAttach + LOCAL aThisFile + LOCAL cMimeText + LOCAL cFile + LOCAL cFname + LOCAL cFext + LOCAL cData + LOCAL oUrl1 LOCAL cTmp := "" LOCAL cTo := "" @@ -154,53 +164,53 @@ FUNCTION hb_SendMail( cServer, nPort, cFrom, aTo, aCC, aBCC, cBody, cSubject, aF ENDIF // cTo - IF ISARRAY( aTo ) - IF Len( aTo ) > 1 - FOR EACH cTo IN aTo + IF ISARRAY( xTo ) + IF Len( xTo ) > 1 + FOR EACH cTo IN xTo IF cTo:__enumIndex() != 1 IF ! Empty( cTo ) - cTmp += cTo + "," + cTmp += tip_GetRawEMail( AllTrim( cTo ) ) + "," ENDIF ENDIF NEXT cTmp := SubStr( cTmp, 1, Len( cTmp ) - 1 ) ENDIF - cTo := aTo[ 1 ] + cTo := tip_GetRawEMail( AllTrim( xTo[ 1 ] ) ) IF Len( cTmp ) > 0 cTo += "," + cTmp ENDIF - ELSEIF ISCHARACTER( aTo ) - cTo := AllTrim( aTo ) + ELSEIF ISCHARACTER( xTo ) + cTo := tip_GetRawEMail( AllTrim( xTo ) ) ENDIF // CC (Carbon Copy) - IF ISARRAY( aCC ) - IF Len( aCC ) > 0 - FOR EACH cTmp IN aCC + IF ISARRAY( xCC ) + IF Len( xCC ) > 0 + FOR EACH cTmp IN xCC IF ! Empty( cTmp ) - cCC += cTmp + "," + cCC += tip_GetRawEMail( AllTrim( cTmp ) ) + "," ENDIF NEXT cCC := SubStr( cCC, 1, Len( cCC ) - 1 ) ENDIF - ELSEIF ISCHARACTER( aCC ) - cCC := AllTrim( aCC ) + ELSEIF ISCHARACTER( xCC ) + cCC := tip_GetRawEMail( AllTrim( xCC ) ) ENDIF // BCC (Blind Carbon Copy) - IF ISARRAY( aBCC ) - IF Len( aBCC ) > 0 - FOR EACH cTmp IN aBCC + IF ISARRAY( xBCC ) + IF Len( xBCC ) > 0 + FOR EACH cTmp IN xBCC IF ! Empty( cTmp ) - cBCC += cTmp + "," + cBCC += tip_GetRawEMail( AllTrim( cTmp ) ) + "," ENDIF NEXT cBCC := SubStr( cBCC, 1, Len( cBCC ) - 1 ) ENDIF - ELSEIF ISCHARACTER( aBCC ) - cBCC := AllTrim( aBCC ) + ELSEIF ISCHARACTER( xBCC ) + cBCC := tip_GetRawEMail( AllTrim( xBCC ) ) ENDIF IF cPopServer != NIL .AND. lPopAuth @@ -214,7 +224,6 @@ FUNCTION hb_SendMail( cServer, nPort, cFrom, aTo, aCC, aBCC, cBody, cSubject, aF RECOVER lReturn := .F. END SEQUENCE - ENDIF IF ! lReturn @@ -222,7 +231,7 @@ FUNCTION hb_SendMail( cServer, nPort, cFrom, aTo, aCC, aBCC, cBody, cSubject, aF ENDIF BEGIN SEQUENCE - oUrl := tUrl():New( iif( lTLS, "smtps://", "smtp://" ) + cUser + iif( Empty( cSMTPPass ), "", ":" + cSMTPPass ) + "@" + cServer + "/" + cTo ) + oUrl := tUrl():New( iif( lTLS, "smtps://", "smtp://" ) + cUser + iif( Empty( cSMTPPass ), "", ":" + cSMTPPass ) + "@" + cServer ) RECOVER lReturn := .F. END SEQUENCE @@ -237,6 +246,12 @@ FUNCTION hb_SendMail( cServer, nPort, cFrom, aTo, aCC, aBCC, cBody, cSubject, aF oMail := tipMail():new() oMail:SetEncoder( cEncoding ) oMail:SetCharset( cCharset ) + oMail:SetHeader( cSubject, cFrom, xTo, xCC, xBCC ) + oMail:hHeaders[ "Date" ] := tip_Timestamp() + IF ! Empty( cReplyTo ) + oMail:hHeaders[ "Reply-to" ] := cReplyTo + ENDIF + IF ! Empty( aFiles ) oAttach := tipMail():new() oAttach:SetEncoder( cEncoding ) @@ -266,19 +281,6 @@ FUNCTION hb_SendMail( cServer, nPort, cFrom, aTo, aCC, aBCC, cBody, cSubject, aF oUrl:cFile := cTo + iif( Empty( cCC ), "", "," + cCC ) + iif( Empty( cBCC ), "", "," + cBCC ) - oMail:hHeaders[ "Date" ] := tip_Timestamp() - oMail:hHeaders[ "From" ] := cFrom - - IF ! Empty( cReplyTo ) - oMail:hHeaders[ "Reply-to" ] := cReplyTo - ENDIF - IF ! Empty( cCC ) - oMail:hHeaders[ "Cc" ] := cCC - ENDIF - IF ! Empty( cBCC ) - oMail:hHeaders[ "Bcc" ] := cBCC - ENDIF - BEGIN SEQUENCE oInmail := tIPClientSMTP():New( oUrl, bTrace ) RECOVER @@ -369,9 +371,6 @@ FUNCTION hb_SendMail( cServer, nPort, cFrom, aTo, aCC, aBCC, cBody, cSubject, aF oInMail:oUrl:cUserid := cFromRaw - oMail:hHeaders[ "To" ] := cTo - oMail:hHeaders[ "Subject" ] := cSubject - FOR EACH aThisFile IN aFiles IF ISCHARACTER( aThisFile ) @@ -456,7 +455,7 @@ FUNCTION hb_SendMail( cServer, nPort, cFrom, aTo, aCC, aBCC, cBody, cSubject, aF oMail:hHeaders[ "X-Priority" ] := Str( nPriority, 1 ) ENDIF - oInmail:Write( oMail:ToString() ) + oInMail:Write( oMail:ToString() ) oInMail:Commit() oInMail:Close()