0

So I am creating a Gmail Sender app using Tkinter and I have a function called send_email and it is inside the SendEmail.py. But every time I run the code it gives me this error:

Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\Users\User\AppData\Local\Programs\Python\Python39\lib\tkinter\__init__.py", line 1885, in __call__
    return self.func(*args)
  File "C:\Users\User\Desktop\Coding\Python\GmailSenderApp\Main.py", line 114, in <lambda>
    send = tk.Button(mainframe, text="Send Email", font=('Calibri', 15), command=lambda: SendEmail.send_email())
AttributeError: partially initialized module 'SendEmail' has no attribute 'send_email' (most likely due to a circular import)

In Main.py I am importing SendMail.py because it contains the function that sends the email Here is Main.py code:

import tkinter as tk
import time
from tkinter import filedialog
import SendEmail

# Main Screen
root = tk.Tk()
root.resizable(False, False)
root.title('Mail Sender')

# Icon
icon = tk.PhotoImage(file='icon.png')
root.iconphoto(False, icon)

# Canvas
canvas = tk.Canvas(root, height=600, width=700)
canvas.pack()

# title
titleFrame = tk.Frame(root)
titleFrame.place(relx=0.5, rely=0.025, relwidth=0.75, relheight=0.1, anchor='n')

title = tk.Label(titleFrame, text="Mail Sender", font=('Calibri', 20))
title.pack()

# Main frame
mainframe = tk.Frame(root, bg='#80c1ff', bd=10)
mainframe.place(relx=0.5, rely=0.15, relwidth=1, relheight=0.85, anchor='n')

# Email
email = tk.Label(mainframe, text="Enter Email:", font=('Calibri', 15))
email.place(y=2.5)

email_str = tk.StringVar()

emailEntry = tk.Entry(mainframe, textvariable=email_str, font=('Calibri', 15))
emailEntry.place(y=35, width=300)

# password
password = tk.Label(mainframe, text="Enter Password:", font=('Calibri', 15))
password.place(y=80)

password_str = tk.StringVar()

passwordEntry = tk.Entry(mainframe, textvariable=password_str, show="\u2022", font=('Calibri', 15))
passwordEntry.place(y=115, width=300)

# receiver
receiver = tk.Label(mainframe, text="Enter Receiver Email:", font=('Calibri', 15))
receiver.place(y=150)

receiver_str = tk.StringVar()

receiverEntry = tk.Entry(mainframe, textvariable=receiver_str, font=('Calibri', 15))
receiverEntry.place(y=185, width=300)

# subject
subject = tk.Label(mainframe, text="Enter Subject:", font=('Calibri', 15))
subject.place(y=220)

subject_str = tk.StringVar()

subjectEntry = tk.Entry(mainframe, textvariable=subject_str, font=('Calibri', 15))
subjectEntry.place(y=255, width=300)

# body
body = tk.Label(mainframe, text="Enter Body:", font=('Calibri', 15))
body.place(x=500, y=2.5)

body_str = tk.StringVar()

bodyEntry = tk.Text(mainframe)
bodyEntry.place(x=380, y=35, width=300)

# notification
notif = tk.Label(mainframe, bg='#80c1ff', font=('Calibri', 15))
notif.place(x=250, y=450)

# attachments array
attachments = []


# add attacments function
def add_attachments():
    filename = filedialog.askopenfilename(initialdir='C:/', title="Select a file to attach to the email")
    attachments.append(filename)

    notif.config(text="Attached " + str(len(attachments)) + " file", fg="green")

    root.update()
    time.sleep(2.5)

    notif.config(text="")


def reset_entries():
    emailEntry.delete(0, 'end')
    passwordEntry.delete(0, 'end')
    receiverEntry.delete(0, 'end')
    subjectEntry.delete(0, 'end')
    bodyEntry.delete("1.0", "end-1c")

    notif.config(text="Entries were reset", fg="green")

    root.update()
    time.sleep(2.5)

    notif.config(text="")


# send button
send = tk.Button(mainframe, text="Send Email", font=('Calibri', 15), command=lambda: SendEmail.send_email())
send.place(y=310, width=150)

# reset button
reset = tk.Button(mainframe, text="Reset", font=('Calibri', 15), command=lambda: ResetEntries.reset_entries())
reset.place(x=220, y=310, width=150)

# attachments button
attachment = tk.Button(mainframe, text="Add Attachments", font=('Calibri', 15), command=lambda: add_attachments())
attachment.place(x=90, y=365, width=200)

# Main loop
root.mainloop()

In the SendMail.py I have import Main.py because I am using variables from that file Here is the SendMain.py code:

import Main
import smtplib
import time
from email.message import EmailMessage


# send function
def send_email():
    try:
        msg = EmailMessage()

        emailText = Main.email_str.get()
        passwordText = Main.password_str.get()
        receiverText = Main.receiver_str.get()
        subjectText = Main.subject_str.get()
        bodyText = Main.bodyEntry.get("1.0", "end-1c")

        msg['Subject'] = subjectText
        msg['From'] = emailText
        msg['To'] = receiverText
        msg.set_content(bodyText)

        if emailText == "" or passwordText == "" or receiverText == "" or subjectText == "" or bodyText == "":
            Main.notif.config(text="All fields are required!", fg="red")

            Main.root.update()
            time.sleep(2.5)

            Main.notif.config(text="")
            return
        else:
            server = smtplib.SMTP('smtp.gmail.com', 587)
            server.starttls()
            server.login(emailText, passwordText)
            server.send_message(msg)

            Main.emailEntry.delete(0, 'end')
            Main.passwordEntry.delete(0, 'end')
            Main.receiverEntry.delete(0, 'end')
            Main.subjectEntry.delete(0, 'end')
            Main.bodyEntry.delete("1.0", "end-1c")

            Main.notif.config(text="Email Sent!", fg="green")

            Main.root.update()
            time.sleep(2.5)

            Main.notif.config(text="")
    except:
        Main.notif.config(text="There was a error please try again", fg="red")

        Main.root.update()
        time.sleep(2.5)

        Main.notif.config(text="")

So does anyone know how to solve this problem I am stuck I can't figure it out. Thanks in advance

YamiAtem
  • 132
  • 1
  • 9
  • The error is clear, you can't import two files circularly, to avoid this problem you should use classes, in one class create class variable with setter and getter and access it from the other class through these functions after object creation. You can easily google what I told if you do not understand. – Ruli Dec 08 '20 at 07:13

1 Answers1

0

You're trying to import a file from a file that imports it. This leads to a circular import. Instead you should put the code you need in both files in a third file and import it in both files.

See the below for an example

variables.py

foo = "bar"

main.py

import variables
import second

print(foo)

second.py

import variables

print(foo)

For your example you will need to move notif, root, emailEntry, passwordEntry, receiverEntry, subjectEntry and bodyEntry into another file, along with the stuff that they rely on.

Minion3665
  • 879
  • 11
  • 25