0

I've set up a hmailserver on my local machine. I'm also using a python script that reads emails. The python script runs fine when I connect to outlook. but I have a problem with the local connection to my hmailserver. I want the script to connect to my local email server (hmailserver) and read the emails from there. I'm having a tough time setting up this connection , and I can't find good documentation relating to hmailserver and python.

import email
import imaplib

EMAIL = 'user1@test.com'
PASSWORD = 'test123'
SERVER = '0.0.0.0/143'#'smtp-mail.outlook.com'

# connect to the server and go to its inbox
mail = imaplib.IMAP4_SSL(SERVER)
mail.login(EMAIL, PASSWORD)
# we choose the inbox but you can select others
mail.select('inbox')

# we'll search using the ALL criteria to retrieve
# every message inside the inbox
# it will return with its status and a list of ids
status, data = mail.search(None, 'ALL')
# the list returned is a list of bytes separated
# by white spaces on this format: [b'1 2 3', b'4 5 6']
# so, to separate it first we create an empty list
mail_ids = []
# then we go through the list splitting its blocks
# of bytes and appending to the mail_ids list
for block in data:
    # the split function called without parameter
    # transforms the text or bytes into a list using
    # as separator the white spaces:
    # b'1 2 3'.split() => [b'1', b'2', b'3']
    mail_ids += block.split()

# now for every id we'll fetch the email
# to extract its content
for i in mail_ids:
    # the fetch function fetch the email given its id
    # and format that you want the message to be
    status, data = mail.fetch(i, '(RFC822)')

    # the content data at the '(RFC822)' format comes on
    # a list with a tuple with header, content, and the closing
    # byte b')'
    for response_part in data:
        # so if its a tuple...
        if isinstance(response_part, tuple):
            # we go for the content at its second element
            # skipping the header at the first and the closing
            # at the third
            message = email.message_from_bytes(response_part[1])

            # with the content we can extract the info about
            # who sent the message and its subject
            mail_from = message['from']
            mail_subject = message['subject']

            # then for the text we have a little more work to do
            # because it can be in plain text or multipart
            # if its not plain text we need to separate the message
            # from its annexes to get the text
            if message.is_multipart():
                mail_content = ''

                # on multipart we have the text message and
                # another things like annex, and html version
                # of the message, in that case we loop through
                # the email payload
                for part in message.get_payload():
                    # if the content type is text/plain
                    # we extract it
                    if part.get_content_type() == 'text/plain':
                        mail_content += part.get_payload()
            else:
                # if the message isn't multipart, just extract it
                mail_content = message.get_payload()

            # and then let's show its result
            print(f'From: {mail_from}')
            print(f'Subject: {mail_subject}')
            print(f'Content: {mail_content}')

above is the code I'm using, connecting to my outlook email worked fine (smtp-mail.outlook.com). but when I substituted the server to connect to my localhost which is 0.0.0.0 on port 143 I get the following error

File "c:/Users/yehya/Desktop/relay.py", line 10, in <module>
    mail = imaplib.IMAP4_SSL(SERVER)
  File "C:\Users\yehya\AppData\Local\Programs\Python\Python38\lib\imaplib.py", line 1297, in __init__
    IMAP4.__init__(self, host, port)
  File "C:\Users\yehya\AppData\Local\Programs\Python\Python38\lib\imaplib.py", line 198, in __init__
    self.open(host, port)
  File "C:\Users\yehya\AppData\Local\Programs\Python\Python38\lib\imaplib.py", line 1310, in open
    IMAP4.open(self, host, port)
  File "C:\Users\yehya\AppData\Local\Programs\Python\Python38\lib\imaplib.py", line 303, in open
    self.sock = self._create_socket()
  File "C:\Users\yehya\AppData\Local\Programs\Python\Python38\lib\imaplib.py", line 1300, in _create_socket
    sock = IMAP4._create_socket(self)
  File "C:\Users\yehya\AppData\Local\Programs\Python\Python38\lib\imaplib.py", line 293, in _create_socket
    return socket.create_connection((host, self.port))
  File "C:\Users\yehya\AppData\Local\Programs\Python\Python38\lib\socket.py", line 787, in create_connection
    for res in getaddrinfo(host, port, 0, SOCK_STREAM):
  File "C:\Users\yehya\AppData\Local\Programs\Python\Python38\lib\socket.py", line 918, in getaddrinfo
    for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
socket.gaierror: [Errno 11001] getaddrinfo failed

Any help is appreciated thanks

  • Localhost is 127.0.0.1. The port isn’t included in the server string, it’s a separate parameter. And port 143 is not SSL, so all in all you want something like imaplib.IMAP(‘127.0.0.1’, 143) (though 143 is implied and doesn’t need to be specified) – Max Jul 11 '21 at 00:05

2 Answers2

0

The issue is with the IP address 0.0.0.0. This is a 'listen' address, and it is not the localhost address. See the wikipedia entry for it.

If you want to loop back to the same machine, you need to use IP address 127.0.0.1. Corresponding wikipedia article.

I also think that the / in the server address might be incorrect. I think you need to replace that with : to specify a port.

Change the line:

SERVER = '0.0.0.0/143'#'smtp-mail.outlook.com'

to the one below:

SERVER = '127.0.0.1:143'#'smtp-mail.outlook.com'
Edo Akse
  • 4,051
  • 2
  • 10
  • 21
  • imaplib doesn’t take ports as part of the server string at all, it must be a separate parameter. `conn = imaplib.IMAP(‘127.0.0.1’, 143). ` – Max Jul 11 '21 at 00:06
0

The comment by max is correct. The correct format is mail = imaplib.IMAP4_SSL(SERVER,143). In my case also the ssl method was not required by the server. So mail=imaplib.IMAP4(SERVER,143)