0

**UPDATE2: In the last bit of code of V2 I swapped smtp.sendmail(email_address, address, msg,) with smtp.sendmail(email_address, phone_book, msg,) Accessing the phone_book directly seems to have solved the issue. Here is the working code for anyone that is looking:

import smtplib

email_address = '' # Your email goes here
email_password = '' # Your password goes here
phone_book = [''] # List of receivers


def Add_Email():
    client_email = input('Email of receiver? ')
    phone_book.append(client_email)

def Add_Subject_Message_Send():    
    with smtplib.SMTP('smtp.gmail.com', 587) as smtp:
            smtp.ehlo()
            smtp.starttls()
            smtp.ehlo()

            smtp.login(email_address, email_password)

            subject = input('Enter your subject here: ')
            body = input('Enter your message here: ')

            msg = f'Subject: {subject}\n\n{body}'

            for i in phone_book:
                address = i
                smtp.sendmail(email_address, phone_book, msg,)


Add_Email()
Add_Subject_Message_Send()

**

**UPDATE: I swapped the code with the simplest versions without GUI. V1 works when subject and body are defined in code. V2 doesn't work when user defines subject and body. Now V2 has this error message:

Traceback (most recent call last):
  File "c:/Users/Me/Desktop/work/infosend/test4.py", line 33, in <module>
    Add_Subject_Message_Send()
  File "c:/Users/Me/Desktop/work/infosend/test4.py", line 29, in Add_Subject_Message_Send
    smtp.sendmail(email_address, address, msg,)
  File "C:\python\lib\smtplib.py", line 885, in sendmail
    raise SMTPRecipientsRefused(senderrs)
smtplib.SMTPRecipientsRefused: {'': (555, b'5.5.2 Syntax error. l15sm65056407wrv.39 - gsmtp')}

**

I'm sending emails using smtplib. As long as subject and body of the message are defined in the code everything works and email gets delivered. When there is no subject or body defined in the code, no errors shows, but message is not delivered.

I want to create a function that will allow me to write what the subject and message is, rather than defining it in the code. My function seems to work, but no messages are being delivered and no error messages received.

Attaching two versions of my code.

First version works. It has defined subject and body.

Second version doesn't work. Includes functions to define subject and body. No errors received in terminal.

V1

import smtplib

email_address = '' # Enter your email address here
email_password = '' # Enter your email password here

phone_book = [''] # Here enter the email of receiver

with smtplib.SMTP('smtp.gmail.com', 587) as smtp: # Connects with GMAIL
            smtp.ehlo()
            smtp.starttls()
            smtp.ehlo()

            smtp.login(email_address, email_password)

            subject = 'test3' # Subject and body defined in code = works
            body = 'test3'

            msg = f'Subject: {subject}\n\n{body}'

            for i in phone_book:
                address = i
                smtp.sendmail(email_address, address, msg,)

V2

    import smtplib

email_address = '' # Your email goes here
email_password = '' # Your password goes here
phone_book = [''] # List of receivers


def Add_Email():
    client_email = input('Email of receiver? ')
    phone_book.append(client_email)

def Add_Subject_Message_Send():    
    with smtplib.SMTP('smtp.gmail.com', 587) as smtp:
            smtp.ehlo()
            smtp.starttls()
            smtp.ehlo()

            smtp.login(email_address, email_password)

            subject = input('Enter your subject here: ')
            body = input('Enter your message here: ')

            msg = f'Subject: {subject}\n\n{body}'

            for i in phone_book:
                address = i
                smtp.sendmail(email_address, address, msg,)


Add_Email()
Add_Subject_Message_Send()
  • You really should reduce this to a [mre]. The GUI code is completely superfluous and unrelated to your question, and makes this much harder for somebody else to review and test. – tripleee Jan 04 '20 at 11:47
  • 1
    Both of these are flawed in that simply concatenating two variables is not the proper way to construct a valid RFC822 email message. It works for simple short strings in English, but will fail for many more interesting strings. As it is, your code hard-codes an empty body in the v2 code, so of course it fails, just as you predict in your problem description. – tripleee Jan 04 '20 at 11:48
  • Could you please reduce your code reference to only your emailing method? – Irfanuddin Jan 04 '20 at 13:03
  • @Irfanuddin Sorry about the confusion. I reduced the code as much as I could and updated it in the post. – S Person D Person Jan 04 '20 at 14:03
  • Thanks for reducing the code. The problem seems to be because of the way you concatenate the strings as @tripleee said. Can you try adding `msg.as_string()` – Irfanuddin Jan 04 '20 at 14:52
  • @SPersonDPerson Check out my solution – Vaibhav Jadhav Jan 07 '20 at 18:22
  • 1
    You mentioned using PySimpleGUI. Have you looked at the Demo Program posted for sending emails? It shows both a GUI as well as how it can be used with smtplib to successfully send emails - https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Email_Send.py – Mike from PSG Jan 08 '20 at 23:08
  • @MikeyB Thank you very much for that, I didn't look through the demo programs. It's awesome. – S Person D Person Jan 10 '20 at 00:22
  • Poesible duplicate of https://stackoverflow.com/questions/11796664/smtplib-sends-blank-message-if-the-message-contain-certain-characters – tripleee Oct 04 '20 at 18:28

3 Answers3

4

I can't reproduce the syntax error you claim to be getting from an earlier version of your code. However, there are some other problems with your attempt.

First off, to troubleshoot, try adding

smtp.set_debuglevel(1)

to show exactly what you are sending. Making sense of the resulting transcript requires an understanding of SMTP, but if you have similar questions in the future, including this transcript could be valuable.

Secondly, sending the same message repeatedly in a loop like that is problematic -- it's wasteful, and could trigger automatic anti-spam controls. To send an identical message to multiple recipients, simply list all the recipients in the call to sendmail (which basically puts them as Bcc: recipients).

Thirdly, you really have a too simple model of what an email message looks like. A minimal message with just a Subject: and a simple text body is valid if both these parts are trivial ASCII strings, but modern email messages require encoding when this is not the case (such as for Unicode strings or binary attachments). You can piece together a valid message yourself, of course, but this is tedious; you should use the Python email library instead.

Here's a brief adaptation from the documentation.

import smtplib
from email.message import EmailMessage

msg = EmailMessage()
msg['From'] = email_address
msg['To'] = ', '.join(phone_book)
msg['Subject'] = subject
msg.set_content(body)

with smtplib.SMTP('smtp.gmail.com', 587) as smtp:
    smtp.ehlo()
    smtp.starttls()
    smtp.ehlo()

    smtp.login(email_address, email_password)

    smtp.send_message(msg)
    smtp.quit()

There are many older examples which use the legacy email.message.Message class, but these should be avoided now. The overhauled email library was introduced in Python 3.3 and became the official and recommended version in 3.5.

tripleee
  • 175,061
  • 34
  • 275
  • 318
  • Thanks for the note. Definitely some weirdness with the older APIs. I just discovered an odd issue using `MIMEMultipart` and `smtp.sendmail()`. When I used the `smtp.send_message()`, the issue went away. I'll switch my code to using `MailMessage` exclusively as all my code uses Python >=3.7.9 – Timothy C. Quinn Apr 12 '23 at 19:21
0

Instead of: address = phone_book

Try using: address = i

I think the problem may be that you're setting the address variable to a list and not a single item in the list.

  • I swapped the code with a simple version as the other wasn't readable. I used address = i as you suggested in that code, but it didn't change anything. – S Person D Person Jan 04 '20 at 14:05
0

Please refer to my code. I have done this and it's working. You can get some lead by refering my code.

Check main function code.

import smtplib

from string import Template

from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText

MY_ADDRESS = 'xyz@gmail.com'
PASSWORD = 'YourPassword'


def get_contacts(filename):
    names = []
    emails = []
    with open(filename, mode='r', encoding='utf-8') as contacts_file:
        for a_contact in contacts_file:
            names.append(a_contact.split()[0])
            emails.append(a_contact.split()[1])
    return names, emails


def read_template(filename):
    with open(filename, 'r', encoding='utf-8') as template_file:
        template_file_content = template_file.read()
    return Template(template_file_content)


def main():
    names, emails = get_contacts('C:/Users/VAIBHAV/Desktop/mycontacts.txt')  # read contacts
    message_template = read_template('C:/Users/VAIBHAV/Desktop/message.txt')
    s = smtplib.SMTP(host='smtp.gmail.com', port=587)
    s.starttls()
    s.login(MY_ADDRESS, PASSWORD)
    for name, email in zip(names, emails):
        msg = MIMEMultipart()  # create a message
        message = message_template.substitute(PERSON_NAME=name.title())
        print(message)
        msg['From'] = MY_ADDRESS
        msg['To'] = email
        msg['Subject'] = "Sending mail to all"
        msg.attach(MIMEText(message, 'plain'))
        s.send_message(msg)
        del msg
    s.quit()
if __name__ == '__main__':
    main()
Vaibhav Jadhav
  • 2,020
  • 1
  • 7
  • 20
  • Thank you again for all the knowledge. At this point I don't think I have enough knowledge and experience to be able to comprehend your answer without someone explaining it to me line by line, but I really appreciate it and I will keep on referencing it as I carry on learning more. Thanks! – S Person D Person Jan 07 '20 at 20:54
  • @SPersonDPerson will surely try to explain my code line by line to you... – Vaibhav Jadhav Jan 07 '20 at 21:31
  • As an aside, it looks like your `email` code was written for an older Python version. The `email` module in the standard library was overhauled in Python 3.6 to be more logical, versatile, and succinct; new code should target the (no longer very) new `EmailMessage` API. Probably throw away this code and start over with modern code from [the Python `email` examples documentation.](https://docs.python.org/3/library/email.examples.html) – tripleee Sep 16 '22 at 12:33