Hello,
I have slightly modified the SMTPClient and SMTPProtocolInterpreter class and packaged an ESMTP.st (as NetClients.ESMTP) (with the Base64 code as NetClients.MIME.Base64). The ESMTP Client is ready for future enhancements, but does his job for my purpose (mostly... Currently, I couldn't mail to GMX.net, but to my company, which is also very restritive with SPAMs... have to investiage it further.) It is currently only capable of using the AUTH LOGIN method for the esmtp protocol, but others could be implemented (with a bit more work, for deciding which authentication method should be used in sending mails...) With the ESMTPClient, mail sending was like the way, you could use the SMTPClient, with a little addition. You should provide the username and password to the client before sending the mail. (The following example is from the "Mail scripting" example from Stephen Woolerton, enhanced by the line for username/password). [client := NetClients.ESMTP.ESMTPClient connectToHost: 'mx.example.com'. client username: 'myUserName' password: 'myPassword'. [client sendMessage: message. If you are interested, drop me a line, would be glad, if I could contribute it to gnu-smalltalk. (it was not such a big modification, after having the base64 code.) Best regards, Joachim. _______________________________________________ help-smalltalk mailing list [hidden email] http://lists.gnu.org/mailman/listinfo/help-smalltalk |
This is COOL!!!, I like it.
On Jun 27, 2009, at 10:33 AM, Joachim Jaeckel wrote: > Hello, > > I have slightly modified the SMTPClient and SMTPProtocolInterpreter > class and packaged an ESMTP.st (as NetClients.ESMTP) (with the > Base64 code as NetClients.MIME.Base64). > > The ESMTP Client is ready for future enhancements, but does his job > for my purpose (mostly... Currently, I couldn't mail to GMX.net, but > to my company, which is also very restritive with SPAMs... have to > investiage it further.) > > It is currently only capable of using the AUTH LOGIN method for the > esmtp protocol, but others could be implemented (with a bit more > work, for deciding which authentication method should be used in > sending mails...) > > With the ESMTPClient, mail sending was like the way, you could use > the SMTPClient, with a little addition. You should provide the > username and password to the client before sending the mail. > > (The following example is from the "Mail scripting" example from > Stephen Woolerton, enhanced by the line for username/password). > > [client := NetClients.ESMTP.ESMTPClient connectToHost: > 'mx.example.com'. > client username: 'myUserName' password: 'myPassword'. > [client sendMessage: message. > > If you are interested, drop me a line, would be glad, if I could > contribute it to gnu-smalltalk. > > (it was not such a big modification, after having the base64 code.) > > Best regards, > Joachim. > > > _______________________________________________ > help-smalltalk mailing list > [hidden email] > http://lists.gnu.org/mailman/listinfo/help-smalltalk > _______________________________________________ help-smalltalk mailing list [hidden email] http://lists.gnu.org/mailman/listinfo/help-smalltalk |
In reply to this post by Joachim Jaeckel
> If you are interested, drop me a line, would be glad, if I could
> contribute it to gnu-smalltalk. Yeah, I was going to ask, where is the code? ;-) It would be great to just include it in SMTP, trying to send EHLO first and HELO if it fails. You can add an exception for no ESMTP and raise it in the login methods. Paolo _______________________________________________ help-smalltalk mailing list [hidden email] http://lists.gnu.org/mailman/listinfo/help-smalltalk |
> Yeah, I was going to ask, where is the code? ;-)
Here it is. > It would be great to just include it in SMTP, trying to send EHLO first > and HELO if it fails. You can add an exception for no ESMTP and raise > it in the login methods. That is a good idea. Today, there's only little time for me (and I have to look into the exception thing in smalltalk a little bit deeper...) And the notes from Stefan haven't it made 'till now into the Base64 code... But to have something to present, here's the early form of code. Paolo, I have pasted some of the Copyrights which I found in the gst-sources to the beginning of the files, hope it's ok. (The package.xml is only for having it as a package in my current project. If it goes into gst, than it would be a good idea to have it in the NetClients.star package, as the others - I think...) Regards, Joachim. "====================================================================== | | Base64 class declarations | | ======================================================================" "====================================================================== | | Copyright 2009 | Written by Joachim Jaeckel | | This file is part of the GNU Smalltalk class library. | | The GNU Smalltalk class library is free software; you can redistribute it | and/or modify it under the terms of the GNU Lesser General Public License | as published by the Free Software Foundation; either version 2.1, or (at | your option) any later version. | | The GNU Smalltalk class library is distributed in the hope that it will be | useful, but WITHOUT ANY WARRANTY; without even the implied warranty of | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser | General Public License for more details. | | You should have received a copy of the GNU Lesser General Public License | along with the GNU Smalltalk class library; see the file COPYING.LIB. | If not, write to the Free Software Foundation, 59 Temple Place - Suite | 330, Boston, MA 02110-1301, USA. | ======================================================================" Namespace current: NetClients.MIME [ Object subclass: Base64 [ Base64 class >> encode: aString [ | chars i j tripple pads c1 c2 c3 c4 b64string | chars := 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'. b64string := String new. pads := 0. i := 1. [i <= aString size] whileTrue: [ j := i +2. (j > aString size) ifTrue: [j := aString size]. tripple := aString copyFrom: i to: j. (tripple size < 3) ifTrue: [ pads := 3 - tripple size. 1 to: pads do: [ :n | tripple growBy: 1. tripple at: (tripple size) put: Character nul. ] ]. b64string growBy: 4. c1 := (tripple at: 1) asInteger bitShift: -2. b64string at: (b64string size -3) put: (chars at: c1 +1). c2 := (((tripple at: 1) asInteger bitAnd: 3) bitShift: 4) bitOr: ((tripple at: 2) asInteger bitShift: -4). b64string at: (b64string size -2) put: (chars at: c2 +1). c3 := (((tripple at: 2) asInteger bitAnd: 15) bitShift: 2) bitOr: ((tripple at: 3) asInteger bitShift: -6). b64string at: (b64string size -1) put: (chars at: c3 +1). c4 := (tripple at: 3) asInteger bitAnd: 63. b64string at: (b64string size) put: (chars at: c4 +1). i := i +3. ]. (pads > 0) ifTrue: [ 1 to: pads do: [ :n | b64string at: (b64string size -n +1) put: $=. ] ]. ^b64string ] ] ] "====================================================================== | | ESMTP protocol support | | ======================================================================" "====================================================================== | | Based on code copyright (c) Kazuki Yasumatsu, and in the public domain | Copyright (c) 2002 Free Software Foundation, Inc. | Adapted by Paolo Bonzini. | Modified for ESMTP by Joachim Jaeckel. | | This file is part of the GNU Smalltalk class library. | | The GNU Smalltalk class library is free software; you can redistribute it | and/or modify it under the terms of the GNU Lesser General Public License | as published by the Free Software Foundation; either version 2.1, or (at | your option) any later version. | | The GNU Smalltalk class library is distributed in the hope that it will be | useful, but WITHOUT ANY WARRANTY; without even the implied warranty of | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser | General Public License for more details. | | You should have received a copy of the GNU Lesser General Public License | along with the GNU Smalltalk class library; see the file COPYING.LIB. | If not, write to the Free Software Foundation, 59 Temple Place - Suite | 330, Boston, MA 02110-1301, USA. | ======================================================================" Namespace current: NetClients.ESMTP [ NetClients.SMTP.SMTPClient subclass: ESMTPClient [ protocolInterpreter [ <category: 'private'> ^ESMTPProtocolInterpreter ] sendMailStream: aStream sender: sender recipients: recipients [ <category: 'accessing'> self connectIfClosed. self clientPI esmtpHello: self getHostname. self clientPI esmtpAuthLogin: self username. self clientPI esmtpPassword: self password. self clientPI smtpMail: sender. recipients do: [:addr | self clientPI smtpRecipient: addr]. self clientPI smtpData: [self clientPI sendMessageWithPeriod: aStream] ] sendMessage: aMessage sender: sender recipients: recipients [ <category: 'accessing'> self connectIfClosed. self clientPI esmtpHello: self getHostname. self clientPI esmtpAuthLogin: self username. self clientPI esmtpPassword: self password. self clientPI smtpMail: sender. recipients do: [:addr | self clientPI smtpRecipient: addr]. self clientPI smtpData: [aMessage printMessageOnClient: self clientPI] ] ] NetClients.SMTP.SMTPProtocolInterpreter subclass: ESMTPProtocolInterpreter [ esmtpHello: domain [ <category: 'esmtp protocol'> self nextPutAll: 'EHLO ',domain; nl. self checkResponse ] esmtpAuthLogin: user [ <category: 'esmtp protocol'> self nextPutAll: 'AUTH LOGIN ', (NetClients.MIME.Base64 encode: user); nl. self checkResponse. "Here comes hopefully the response 334" ] esmtpPassword: password [ <category: 'esmtp protocol'> self nextPutAll: (NetClients.MIME.Base64 encode: password); nl. self checkResponse "Here comes hopefully the response 235" ] checkResponse: response ifError: errorBlock [ <category: 'private'> | status | status := response status. "Positive Completion reply" status = 211 ifTrue: ["System status, or system help reply" ^self]. status = 214 ifTrue: ["Help message" ^self]. status = 220 ifTrue: ["Service ready" ^self]. status = 221 ifTrue: ["Service closing channel" ^self]. status = 235 ifTrue: ["Authentication successful" ^self]. status = 250 ifTrue: ["Requested mail action okay" ^self]. status = 251 ifTrue: ["User not local; will forward" ^self]. status = 334 ifTrue: ["Authetication password" ^self]. "Positive Intermediate reply" status = 354 ifTrue: ["Start mail input" ^self]. "Transient Negative Completion reply" status = 421 ifTrue: ["Service not available" ^errorBlock value]. status = 450 ifTrue: ["Requested mail action not taken" ^errorBlock value]. status = 451 ifTrue: ["Requested action aborted" ^errorBlock value]. status = 452 ifTrue: ["Requested action not taken" ^errorBlock value]. "Permanent Negative Completion reply" status = 500 ifTrue: ["Syntax error" ^errorBlock value]. status = 501 ifTrue: ["Syntax error in parameters" ^errorBlock value]. status = 502 ifTrue: ["Command not implemented" ^errorBlock value]. status = 503 ifTrue: ["Bad sequence of commands" ^errorBlock value]. status = 504 ifTrue: ["Command parameter not implemented" ^errorBlock value]. status = 550 ifTrue: ["Requested action not taken" ^errorBlock value]. status = 551 ifTrue: ["User not local; please try" ^errorBlock value]. status = 552 ifTrue: ["Requested mail action aborted" ^errorBlock value]. status = 553 ifTrue: ["Requested action not taken" ^errorBlock value]. status = 554 ifTrue: ["Transaction failed" ^errorBlock value]. "Unknown status" ^errorBlock value "334 password z.B." "235 Authentication successfull" ] ] ] <package> <name>NetClientsExtensions</name> <prereq>NetClients</prereq> <filein>Base64.st</filein> <filein>ESMTP.st</filein> <file>Base64.st</file> <file>ESMTP.st</file> </package> PackageLoader fileInPackage: 'NetClientsExtensions'. Object subclass: EsmtpTest [ sendEmailMsgTo: recipient from: sender through: host as: username with: password [ | mailmsg message client | mailmsg := 'From: %1 To: %2 Subject: %3 %4 ' bindWith: sender with: recipient with: 'Testmail from Smalltalk' with: 'This is a genereated testmail with the ESMTP package!'. message := NetClients.MIME.MimeEntity readFrom: mailmsg readStream. [client := NetClients.ESMTP.ESMTPClient connectToHost: host. client username: username password: password. [client sendMessage: message. Transcript showCr: 'send mail'] ensure: [client close] ] on: Error do: [:sig | Transcript showCr: 'Error: Couldnt connect to SMTP server.']. ] ] EsmtpTest new sendEmailMsgTo: '[hidden email]' from: '[hidden email]' through: 'mail.example.com' as: '[hidden email]' with: 'topSecret'. _______________________________________________ help-smalltalk mailing list [hidden email] http://lists.gnu.org/mailman/listinfo/help-smalltalk |
On Sat, 27 Jun 2009 14:30:03 +0200
Joachim Jaeckel <[hidden email]> wrote: > Paolo, I have pasted some of the Copyrights which I found in the > gst-sources to the beginning of the files, hope it's ok. Interesting point ... if you copy a copyright notice, aren't you already in violation of copyright, when you claim that the file contents are copyrighted by yourself? waaaaa s. _______________________________________________ help-smalltalk mailing list [hidden email] http://lists.gnu.org/mailman/listinfo/help-smalltalk |
In reply to this post by Joachim Jaeckel
Hello again,
I currently "finished" the work on the Base64 class and here it is. If I have time or you recommend it as an important part, I'll enhance it with base64 after MIME, base 64 after PEM and base64 with the URL-save alphabet. (The changes are only CRLF after 76 or 64 Bytes of data and for URLs, using another alphabet which differs in using the character '-' and '_' instead of '+' and '/'.) But the current implementation would be enough for my current needs. Best regards, Joachim. "====================================================================== | | Base64 class declarations | | ======================================================================" "====================================================================== | | Copyright 2009 | Written by Joachim Jaeckel | | This file is part of the GNU Smalltalk class library. | | The GNU Smalltalk class library is free software; you can redistribute it | and/or modify it under the terms of the GNU Lesser General Public License | as published by the Free Software Foundation; either version 2.1, or (at | your option) any later version. | | The GNU Smalltalk class library is distributed in the hope that it will be | useful, but WITHOUT ANY WARRANTY; without even the implied warranty of | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser | General Public License for more details. | | You should have received a copy of the GNU Lesser General Public License | along with the GNU Smalltalk class library; see the file COPYING.LIB. | If not, write to the Free Software Foundation, 59 Temple Place - Suite | 330, Boston, MA 02110-1301, USA. | ======================================================================" Namespace current: NetClients.MIME [ Object subclass: Base64 [ Base64 class >> encode: aString [ | chars i j copyTo triple c1 c2 c3 c4 aStringSize b64SizeMultiplier b64String | chars := 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'. aStringSize := aString size. b64SizeMultiplier := aStringSize // 3. (aStringSize \\ 3 ~= 0) ifTrue: [b64SizeMultiplier := b64SizeMultiplier +1]. b64String := String new: (b64SizeMultiplier * 4) withAll: $=. i := j := 1. [i <= aStringSize] whileTrue: [ copyTo := i +2. (copyTo > aStringSize) ifTrue: [copyTo := aStringSize]. triple := aString copyFrom: i to: copyTo. triple growBy: 1. triple at: (triple size) put: Character nul. c1 := (triple at: 1) asInteger bitShift: -2. b64String at: j put: (chars at: c1 +1). j := j +1. c2 := (((triple at: 1) asInteger bitAnd: 3) bitShift: 4) bitOr: ((triple at: 2) asInteger bitShift: -4). b64String at: j put: (chars at: c2 +1). j := j +1. (triple size > 2) ifTrue: [ c3 := (((triple at: 2) asInteger bitAnd: 15) bitShift: 2) bitOr: ((triple at: 3) asInteger bitShift: -6). b64String at: j put: (chars at: c3 +1). j := j +1. ]. (triple size > 3) ifTrue: [ c4 := (triple at: 3) asInteger bitAnd: 63. b64String at: j put: (chars at: c4 +1). j := j +1. ]. i := i +3. ]. ^b64String ] Base64 class >> decode: aString [ | chars b64StringSize i j quad padding string c1 c2 c3 | chars := 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'. b64StringSize := aString size. "Size should be a multiple of 4" (b64StringSize \\ 4 ~= 0) ifTrue: [ ^NotBase64Encoded new signal: ('String: ''%1'' is not base64 encoded' bindWith: aString) ]. "and should contain only defined character" aString do: [:char | (chars indexOf: char) = 0 & (char ~= $=) ifTrue: [ ^NotBase64Encoded new signal: ('String: ''%1'' is not base64 encoded' bindWith: aString) ] ]. padding := 0. i := b64StringSize. [(aString at: i) = $=] whileTrue: [ padding := padding +1. i := i -1. ]. string := String new: (b64StringSize // 4 * 3 - padding) withAll: Character nul. i := j := 1. [i <= b64StringSize] whileTrue: [ quad := aString copyFrom: i to: i +3. c1 := ((chars indexOf: (quad at: 1)) asInteger -1 bitShift: 2) bitOr: ((chars indexOf: (quad at: 2)) asInteger -1 bitShift: -4). string at: j put: c1 asCharacter. j := j +1. (quad at: 3) ~= $= ifTrue: [ c2 := (((chars indexOf: (quad at: 2)) asInteger -1 bitAnd: 15) bitShift: 4) bitOr: ((chars indexOf: (quad at: 3)) asInteger -1 bitShift: -2). string at: j put: c2 asCharacter. j := j +1. ]. (quad at: 4) ~= $= ifTrue: [ c3 := (((chars indexOf: (quad at: 3)) asInteger -1 bitAnd: 3) bitShift: 6) bitOr: ((chars indexOf: (quad at: 4)) asInteger -1). string at: j put: c3 asCharacter. j := j +1. ]. i := i +4. ]. ^string ] ] Notification subclass: NotBase64Encoded [ description [ ^'String is not Base64 encoded' ] ] ] _______________________________________________ help-smalltalk mailing list [hidden email] http://lists.gnu.org/mailman/listinfo/help-smalltalk |
> I currently "finished" the work on the Base64 class and here it is. > > If I have time or you recommend it as an important part, I'll enhance it > with base64 after MIME, base 64 after PEM and base64 with the URL-save > alphabet. I'll be committing it tonight as NetProtocolInterpreter class >> #encodeBase64:. I plan to do some changes. You can look at them for your own education and benchmark the difference (I didn't). For decoding, I'm adding Integer >> #digitAt: and using the existing code instead. Paolo _______________________________________________ help-smalltalk mailing list [hidden email] http://lists.gnu.org/mailman/listinfo/help-smalltalk |
> I plan to do some changes. You can look at them for
> your own education and benchmark the difference (I didn't). No problem! Looking forward to see your "tune up". > For decoding, I'm adding Integer >> #digitAt: and using the existing > code instead. My first try was a modification to the existing code, that it accepts a string as the only parameter, but then I had problems with some encoded strings. That was the time where I decided to have a look into the rfc and do an implementation by my own. (The problematic text-string in my case was 'ABCdef'. First do an encode to: QUJDZGVm and than the decode with the existing method with my modification fails. Other strings were not a problem.) Best regards, Joachim. _______________________________________________ help-smalltalk mailing list [hidden email] http://lists.gnu.org/mailman/listinfo/help-smalltalk |
Joachim Jaeckel wrote:
> > I plan to do some changes. You can look at them for >> your own education and benchmark the difference (I didn't). > > No problem! Looking forward to see your "tune up". > >> For decoding, I'm adding Integer >> #digitAt: and using the existing >> code instead. > > My first try was a modification to the existing code, that it accepts a > string as the only parameter, but then I had problems with some encoded > strings. That was the time where I decided to have a look into the rfc > and do an implementation by my own. Yeah, I fixed that now. Paolo _______________________________________________ help-smalltalk mailing list [hidden email] http://lists.gnu.org/mailman/listinfo/help-smalltalk |
In reply to this post by Joachim Jaeckel
I finally integrated this, thanks! (commit fd7929d).
Paolo _______________________________________________ help-smalltalk mailing list [hidden email] http://lists.gnu.org/mailman/listinfo/help-smalltalk |
> I finally integrated this, thanks! (commit fd7929d).
You'r welcome! (If I could say that for such a tiny "contribution"... or the idea). And to answer your other question: Everything is a learning expirience! Even here with: ('%<EHLO|HELO>1 %2' % {esmtp. domain}) to found it defined in the CharacterArray class! :-) Cool! Thanks! Joachim. _______________________________________________ help-smalltalk mailing list [hidden email] http://lists.gnu.org/mailman/listinfo/help-smalltalk |
Free forum by Nabble | Edit this page |