help-smalltalk
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Help-smalltalk] NetClients.ESMTP package


From: Joachim Jaeckel
Subject: Re: [Help-smalltalk] NetClients.ESMTP package
Date: Sat, 27 Jun 2009 14:30:03 +0200
User-agent: Mozilla-Thunderbird 2.0.0.19 (X11/20090103)

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: 'address@hidden'
    from: 'address@hidden'
    through: 'mail.example.com'
    as: 'address@hidden'
    with: 'topSecret'.

reply via email to

[Prev in Thread] Current Thread [Next in Thread]