2009-02-14 6 views
3

J'ai un morceau de code très simple que j'ai utilisé dans les versions précédentes de Python sans problèmes (version 2.5 et antérieures). Maintenant avec 3.0, le code suivant donne l'erreur sur la ligne de connexion "l'argument 1 doit être une chaîne ou un tampon, pas un str".Python 3.0 smtplib

import smtplib 

    smtpserver = 'mail.somedomain.com' 
    AUTHREQUIRED = 1      # if you need to use SMTP AUTH set to 1 
    smtpuser = '[email protected]' # for SMTP AUTH, set SMTP username here 
    smtppass = 'somepassword'   # for SMTP AUTH, set SMTP password here 
    msg = "Some message to send" 

    RECIPIENTS = ['[email protected]'] 
    SENDER = '[email protected]' 

    session = smtplib.SMTP(smtpserver) 

    if AUTHREQUIRED: 
     session.login(smtpuser, smtppass) 

    smtpresult = session.sendmail(SENDER, RECIPIENTS, msg) 

Google montre qu'il ya quelques problèmes avec cette erreur de ne pas être clair, mais je ne peux toujours pas comprendre ce que je dois essayer de le faire fonctionner. Les suggestions incluaient la définition du nom d'utilisateur comme b "nom d'utilisateur", mais cela ne semble pas fonctionner non plus.

+0

Vous auriez dû inclure la traceback – hop

+1

Je chercherais certainement ceci sur le traqueur de bug de Python et/ou créerais un nouveau rapport de bogue, car cela ressemble clairement à un bogue dans smtplib ou aux modules sous-jacents comme l'email .base65mime – Jay

+0

La branche 2.6 est toujours maintenue et il y en aura 2.7 aussi, donc vous n'avez pas besoin de changer pour le moment. – George

Répondre

4

MISE À JOUR: juste remarqué d'un regard sur le bug tracker il y a une solution a également suggéré:

Modifier smtplib.py et remplacer la définition encode_plain() existante par:

def encode_plain(user, password): 
    s = "\0%s\0%s" % (user, password) 
    return encode_base64(s.encode('ascii'), eol='') 

Testé ici mon installation et cela fonctionne correctement.

3
Traceback (most recent call last): 
    File "smtptest.py", line 18, in <module> 
    session.login(smtpuser, smtppass) 
    File "c:\Python30\lib\smtplib.py", line 580, in login 
    AUTH_PLAIN + " " + encode_plain(user, password)) 
    File "c:\Python30\lib\smtplib.py", line 545, in encode_plain 
    return encode_base64("\0%s\0%s" % (user, password)) 
    File "c:\Python30\lib\email\base64mime.py", line 96, in body_encode 
    enc = b2a_base64(s[i:i + max_unencoded]).decode("ascii") 
TypeError: b2a_base64() argument 1 must be bytes or buffer, not str 

Votre code est correct. Ceci est un bogue dans smtplib ou dans le base64mime.py. Vous pouvez suivre le problème ici: http://bugs.python.org/issue5259

Espérons que les développeurs publieront bientôt un correctif.

+0

battu moi :-) Il semble qu'il y ait plus que ce problème présent en essayant d'utiliser Python 3.0 avec smtplib car même après avoir patché les réponses d'erreur de base64mime.py sont renvoyées par le serveur de messagerie alors qu'elles ne devraient pas l'être, Je peux dire. – Jay

+0

stupide moi pour ne pas vérifier le lien bug tracker, le changement de suggestion posté à encode_plain() fonctionne très bien avec quelques petits changements à smtplib.py – Jay

+0

"doit être octets ou tampon, pas str" est un bug trouvé dans de nombreux endroits dans la bibliothèque standard, malheureusement. –

2

Comme une variation sur la réponse de Jay, plutôt que d'éditer smtplib.py, vous pourriez le "patch de singe" au moment de l'exécution.

mettre quelque part dans votre code:


def encode_plain(user, password): 
    s = "\0%s\0%s" % (user, password) 
    return encode_base64(s.encode('ascii'), eol='') 

import smtplib 
encode_plain.func_globals = vars(smtplib) 
smtplib.encode_plain = encode_plain 

C'est un peu laid, mais utile si vous souhaitez déployer votre code sur d'autres systèmes sans modifier leurs bibliothèques Python.