TypeError: object of type 'method' has no len() | Trying to attach file to email msg

4.6k views Asked by At

I'm using Python 3 and I'm trying to attach a file to an email message. I'm pretty new at MIME and SMTP stuff. So this is my function:

def func():
path = mypath
for file in glob.glob(path + "\\happy*"):
    print(file)
    sender = myemail
    senderto = someonesemail
    msg = MIMEMultipart('alternative')
    msg['Subject'] = 'The File'
    msg['From'] = sender
    msg['To'] = senderto
    body = "File"
    msg.attach(MIMEText(body, 'plain'))
    part = MIMEBase('application', 'octet-stream')
    part.set_payload(open(file, encoding='charmap').read())
    encoders.encode_base64(part)
    part.add_header('Content-Disposition', "attachment; filename= %s" % file)
    msg.attach(part)
    global smtpSettings
    smtpSettings = smtplib.SMTP(host=myhost, port=587)
    print("Step 1 Complete")
    smtpSettings.login(smtpusername, smtppassword)
    print("Step 2 Complete")
    smtpSettings.sendmail(sender, senderto, msg.as_string)
    print("Step 3 Complete")
    smtpSettings.quit()
    print("Success")

Side note: senderto = receiver. The output I get is:

Traceback (most recent call last):
  File "C:\Python34\lib\tkinter\__init__.py", line 1533, in __call__
    return self.func(*args)
  File "C:/Users/Luis/Desktop/PYTHON/smtptestes.py", line 73, in func
    smtpSettings.sendmail(sender, senderto, msg.as_string)
  File "C:\Python34\lib\smtplib.py", line 769, in sendmail
    esmtp_opts.append("size=%d" % len(msg))
TypeError: object of type 'method' has no len()
2

There are 2 answers

0
fferri On BEST ANSWER

Fix in step 3, change

smtpSettings.sendmail(sender, senderto, msg.as_string)

to

smtpSettings.sendmail(sender, senderto, msg.as_string())

because as_string is a method

0
PascalVKooten On

I'm the maintainer of yagmail, it's a package that makes it a lot easier to send emails (with or without attachments).

import yagmail
yag = yagmail.SMTP(myemail, 'mypassword')
yag.send(to = someonesemail, subject = 'The File', contents = ['File', file])

Only three lines needed for the sending of the email. Nice!

The contents will smartly guess that the file variable string points to a file, and thus attach it.

Full code might be:

import yagmail
import glob

def func(path, user, pw, ):        
    subject = 'The File' 
    body = "File"  
    yag = yagmail.SMTP(user, pw, host = myhost)
    for fname in glob.glob(path + "\\happy*"): 
        yag.send(someonesemail, subject, [body, fname])

 func(mypath, smtpusername, smtppassword)