Error using python email module

I have an app that receives email and has been working for some time.

As of April (20th, I think), it started throwing an error on a line where I call email.utils.parseaddr from python’s standard email module:

AttributeError: module 'email' has no attribute 'utils' at messages, line 15
called from messages, line 75
called from /downlink/anvil/email.py, line 30

Is there some naming conflict going on here that didn’t use to exist?

Hi @owen.campbell,

Can you share the relevant code? I’m making a blind guess here, but it’s possible you’re doing from anvil import * at the top of your code, after you import email. If the anvil.email module is installed, this will overwrite the email name for that module, so email.utils tries to get the utils attribute from the anvil.email module rather than from the built-in email module!

(My guess about what’s changed is either some piece of preloading we’re doing for performance, or a dependency – or some other code – which has done import anvil.email.)

This is why most people advise against from foo import * statements :slight_smile:

Here you go. No starred imports for me!

I did suspect some sort of clash between the email and anvil.email imports, but this has been working fine for a few months.

import datetime as dt
import email
from uuid import uuid4

import anvil.email
import anvil.secrets
import anvil.server
import anvil.tables as tables
import anvil.tables.query as q
import anvil.users
from anvil.tables import app_tables


def parse_message(msg):
  sender, sender_email = email.utils.parseaddr(msg.get_header("From"))
  ...

@anvil.email.handle_message()
def handler(msg):
  parsed_message = parse_message(msg)
  ...

I’ve also tried

import email as pyemail

...

def parse_message(msg):
  sender, sender_email = pyemail.utils.parseaddr(msg.get_header("From"))

but it made no difference

Wow. Unless there’s something seriously dodgy in another module, I’m going to call that a bug in Anvil. Can you produce a reproduction case we can clone?

I can’t reproduce this. I copied the code into a new app (on my own account) and it runs perfectly.

However, on the original app, it’s throwing an error in the app log for every incoming message.

Further investigation - if I clone the app, I get the same errors in the clone. If I copy and paste the code from the offending server module into an otherwise empty app, it works fine.

This is corroborating my suspicion that something else in your app is messing with the namespacing. Try starting with a clone, and then gradually deleting all the other server modules?

Got it!!! It depends on the python version used.

Here’s a minimal demo of the problem: https://anvil.works/build#clone:NLQEI5BMFKOIU55V=3EIHF4XPSJUP5ETBWNFEGBVU

If the server module is Basic Python 3, it works fine. If you set it to Full Python 3, the error gets raised.

Is there anything I can do about this one?

I can’t use Basic Python because I need some of the libraries in the Full environment.

I’m using the email module to get the details of the original sender. If there’s another way to do that, it might get me under way again.

@meredydd Have you managed to reproduce this from my demo?

Hi Owen,

It turns out that this shouldn’t work in Basic Python 3 either - you haven’t imported the email.utils module! This works:

import email as pyemail
import email.utils as pyemail_utils

...

sender, sender_email = pyemail_utils.parseaddr(msg.get_header("From"))

Hope that helps!

Aggghhhhhh!!! Thank you, thank you, thank you! (Again)

@daviesian Any clue as to why this working perfectly until mid April?

No idea, I’m afraid, possibly a change to the built-in email module. In any case, it definitely shouldn’t have worked!

1 Like