Giter Site home page Giter Site logo

python-slimta's Introduction


About

slimta is a configurable MTA based on the python-slimta libraries. While the purpose of the python-slimta library is to avoid configuration files and allow full control via Python code, the slimta project recognizes that not everyone will want or need that level of control. Setup, configuration, and execution of slimta is designed to be familiar to non-programmers.

The slimta project is released under the MIT License.

Getting Started

Install slimta from PyPi:

$ pip install slimta

Pip should pull in all the required dependencies. Next, we create the basic configuration files:

$ slimta-setup config

This creates 3 files, in ~/.slimta/ or wherever you specified. The sample configs are designed to work out of the box, so lets give it a shot:

$ slimta --no-daemon

In another terminal, let's connect to port 1025 to see if it's working. After the banner (the line beginning with 220 ), type in QUIT to end the session:

$ telnet localhost 1025
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
220 localhost.localdomain ESMTP example.com Mail Delivery Agent
QUIT
221 2.0.0 Bye
Connection closed by foreign host.

Port 1025 is fully capable of accepting mail in the SMTP session, but is configured by default with the blackhole relay to silently discard messages. You can also try it out with the built-in Python SMTP libraries:

>>> import smtplib
>>> smtplib.SMTP('localhost', 1025).sendmail('[email protected]',
                                             ['[email protected]'],
                                             'test message')

At this point, we're still a little ways off from where you'd probably like to be: actually sending and receiving email to the Internet. Please check out the Usage Manual for information on configuring slimta to your liking, including more advanced and custom setups.

python-slimta's People

Contributors

brycedrennan avatar drewlander avatar gpatel-fr avatar icgood avatar jocelyndelalande avatar nicolaslm avatar rafaelnovello avatar rgcarrasqueira avatar toxinu avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

python-slimta's Issues

How to handle bounce envelope in custom Relay?

If I implement a custom Relay which handles inbound mails and something goes wrong, the celery queue (I guess other queeus too) send a bounce message to the custom Relay.

Should the custom Relay handle bounce messages too? Or what's the best way to get rid of the bounce envelope? Should the queue not use a different Relay for bounce envelope?

I'm asking because a custom inbound Relay has only to do with receiving mails.

any way of convincing StaticSmtpRelay to use a certain ip when relaying an email?

I am using slimta for a custom whitelabel transactional email platform. I am using slimta for antispam, authentication and some other taks, but i forward all the emails to a sendgrid account. I'd like to change that in the future, and deliver the emails myself. I want to create 2-3 ip pools for each customer rating (good, bad, neutral) so i can segregate my traffic on different ips, eventually based on target domain as well.
I was thinking starting one or more instances based on StaticSmtpRelay per each ip, and read the incoming mails from a distributed message queue. Is there a better solution which i'm missing?
Thanks.
btw great library.

Expose socket_creator Relay option

Needing to bind to a specific outbound IP is a very common and important pattern in mail. This "hidden" option should be exposed and documented.

References #28

Documentation on slimta.policy and list versus generators

The slimta.policy documentation says that the apply method may:

"Optionally return a new list of Envelope objects to replace the given envelope going forward. Returning None or an empty list will keep using envelope."

It appears that apply may also return a generator instead of a list. So perhaps apply only needs to return an iterable?

Also, the slimta.policy documentation does not say that apply may modify the existing envelope in place instead of creating a new one. It might be nice to be explicit about this.

For reference, the slimta.policy documentation is here:
http://docs.slimta.org/en/latest/api/slimta.policy.html

StaticSmtpRelay does not seem to care about connect_timeout or command_timeout

I've sent an email to a colleague's email server using a StaticSmtpRelay, and i've receive this traceback

Traceback (most recent call last):
  File "debug_slowconn/1.py", line 20, in <module>
    mx.attempt(new_envelope, 0)
  File "/root/venv_smtpout/site-packages/slimta/relay/smtp/mx.py", line 220, in attempt
    return relayer.attempt(envelope, attempts)
  File "/root/venv_smtpout/site-packages/slimta/relay/pool.py", line 93, in attempt
    return result.get()
  File "/root/venv_smtpout/site-packages/gevent/event.py", line 294, in get
    return self.get(block=False)
  File "/root/venv_smtpout/site-packages/gevent/event.py", line 273, in get
    return self._raise_exception()
  File "/root/venv_smtpout/site-packages/gevent/event.py", line 254, in _raise_exception
    reraise(*self.exc_info)
  File "/root/venv_smtpout/site-packages/gevent/_util_py2.py", line 8, in reraise
    raise type, value, tb
SmtpTransientRelayError: Transient failure on [unknown command]: 421 4.3.0 Connection was closed prematurely

The culprit seems to be in slimta/smtp/io.py in raw_recv, in the second raise ConnectionLost(). The destination MX is accepting my SMTP connection, but it doesn't greet me until it can resolve my reverse ip, so the connection hangs for 20-21 seconds. After that, i get a nice greeting from exim and i could carry on. Unfortunately, slimta hangs and dies. Have you managed to get this error in production? May this be signaling a bigger bug?

No way to do the following scenario in 3.0.0 easier than in 2.0.0

Acquire an Envelope

  • inspect the recipient and the sender
  • External logic decides an ip and an ehlo
  • Attempt the envelope thru a MxSmtpRelay which is constructed with a socket_creator which uses the said ip and using the decided ehlo.

There are benefits in using the MxSmtpRelay class, because it can re-use a non-closed socket, via the idle_timeout parameter. The new 3.0.0 capability of providing the echlo_as as a function isn't very usefull, as you may want to use a different ehlo on the same MxSmtpRelay class. I just can't imagine using it, because i create an object which holds multiple MxSmtpRelay instances, each with it's own source_ip.

I've worked around this in 2.0.0 and 3.0.0 looks as difficult.

ProxyAuth

There's ProxyQueue, but no ProxyAuth. It would be a nice feature.

Regarding how to implement this, icgood said on IRC:

regarding your question about authentication.. it's not straightforward, no, but it is do-able.. what you'd do is create a new ServerMechanism whose server_attempt() method simply passes the response string through to the proxy server

It seems more complex to me: the client should know which mechanism types are available before the authentication starts.

Relay results as a dict

Rather than returning relay results as a sequence that maps 1-1 to the envelope.recipients field, just return it as a dict where the key is the recipient and the value is the relay result.

Incompatibility with Django

Working on an application using both Django & slimta (and thus gevent).

There is some errors with Django dev tools (test runner, and devserver) :

Traceback (most recent call last):
  File "./manage.py", line 10, in <module>
    execute_from_command_line(sys.argv)
  File "/home/jocelyn/.virtualenvs/gevent3/lib/python3.4/site-packages/django/core/management/__init__.py", line 350, in execute_from_command_line
    utility.execute()
  File "/home/jocelyn/.virtualenvs/gevent3/lib/python3.4/site-packages/django/core/management/__init__.py", line 342, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/home/jocelyn/.virtualenvs/gevent3/lib/python3.4/site-packages/django/core/management/commands/test.py", line 30, in run_from_argv
    super(Command, self).run_from_argv(argv)
  File "/home/jocelyn/.virtualenvs/gevent3/lib/python3.4/site-packages/django/core/management/base.py", line 360, in run_from_argv
    connections.close_all()
  File "/home/jocelyn/.virtualenvs/gevent3/lib/python3.4/site-packages/django/db/utils.py", line 235, in close_all
    connection.close()
  File "/home/jocelyn/.virtualenvs/gevent3/lib/python3.4/site-packages/django/db/backends/base/base.py", line 263, in close
    self.validate_thread_sharing()
  File "/home/jocelyn/.virtualenvs/gevent3/lib/python3.4/site-packages/django/db/backends/base/base.py", line 523, in validate_thread_sharing
    % (self.alias, self._thread_ident, thread.get_ident()))
django.db.utils.DatabaseError: DatabaseWrapper objects created in a thread can only be used in that same thread. The object with alias 'default' was created in thread id 140001273534208 and this is thread id 140001196547568.

That's caused by the gevent monkey-patch_all() of the threading, one suggested solution is not to patch threading :

 gevent.monkey.patch_all(socket=True, dns=True, time=True, select=True,thread=False, os=True, ssl=True, httplib=False, aggressive=True)

This suggestion seems fine to be but as I'm not expert at all with gevent, I prefer to ask before submiting patch : would this theoretically break slimta ?

Handle Timeout errors

Hi!

I'm using python-slimta with some success but sometimes I get a Timeout error and I would like to handle then like a bounce. Is there a way to do that?

Error traceback:

Traceback (most recent call last):
  File "/home/rafael/prj/mailerweb/disparador/local/lib/python2.7/site-packages/gevent/greenlet.py", line 390, in run
    result = self._run(*self.args, **self.kwargs)
  File "/home/rafael/prj/mailerweb/disparador/src/python-slimta/slimta/relay/smtp/client.py", line 203, in _run
    self._connect()
  File "/home/rafael/prj/mailerweb/disparador/src/python-slimta/slimta/relay/smtp/client.py", line 76, in _connect
    self.socket = self._socket_creator(self.address)
  File "/home/rafael/prj/mailerweb/disparador/src/python-slimta/slimta/relay/smtp/client.py", line 69, in _socket_creator
    socket = create_connection(address)
  File "/home/rafael/prj/mailerweb/disparador/local/lib/python2.7/site-packages/gevent/socket.py", line 646, in create_connection
    sock.connect(sa)
  File "/home/rafael/prj/mailerweb/disparador/local/lib/python2.7/site-packages/gevent/socket.py", line 376, in connect
    wait_readwrite(sock.fileno(), event=self._rw_event)
  File "/home/rafael/prj/mailerweb/disparador/local/lib/python2.7/site-packages/gevent/socket.py", line 215, in wait_readwrite
    switch_result = get_hub().switch()
  File "/home/rafael/prj/mailerweb/disparador/local/lib/python2.7/site-packages/gevent/hub.py", line 164, in switch
    return greenlet.switch(self)
Timeout: 10.0 seconds
<SmtpRelayClient at 0x19d9550> failed with Timeout

Include command in SmtpRelayClient errors

The error reply generated here does not properly carry over the command field of the original Reply that caused the exception. This causes errors to say [unknown command] even when they happened while waiting for the response to a command.

Possible bug? Do I need to set self.session.auth_result myself?

Does my Auth class need so set self.session.auth_result? I thought Slimta would do this for me. Nothing in the Auth documentation says I need to do this.

http://docs.slimta.org/en/latest/api/slimta.smtp.auth.html

I'm authenticating successfully, but later on in my Validator, self.session.auth_result is None. Which surprised me.

>   220 ESMTP server
 -  EHLO ripple
>   250-Hello ripple
>   250-8BITMIME
>   250-AUTH LOGIN PLAIN
>   250-ENHANCEDSTATUSCODES
>   250 PIPELINING
 -  AUTH PLAIN [base64 data]
>   235 2.7.0 Authentication successful
 -  MAIL FROM:<alice@local> 
>   250 2.1.0 Sender <alice@local> Ok
 -  RCPT TO:<bob@remote>
>   550 5.0.0 relay not permitted
expected: 250 

And here is a trimmed down snippet from my Validator:

  def handle_rcpt (self, reply, recipient):
    print 'handle_rcpt  %s' % recipient
    print '  auth %s' % self.session.auth_result
    if self.session.auth_result:
      # todo: confirm sender matches auth login                                 
      pass
    else:
      print '  no auth'
      reply.code = '550'
      reply.message = 'relay not permitted'

It prints:
handle_rcpt bob@remote
auth None
no auth


This is interesting: self.session is different in my Auth and Validator! Unexpected!

('verify_secret', 'alice@local', 'pass_alice', '')
session <slimta.smtp.server.Server object at 0xa3e00ec>
auth_result None
handle_rcpt bob@remote
session <slimta.edge.smtp.SmtpSession object at 0xa3dcfec>
auth_result None

Note: I expect auth_result to be None inside verify_secret, because it is verify_secret that performs the authentication.


My Validator needs to know more than whether or not authentication was successful. It needs to know who authenticated successfully (and compare it to the MAIL FROM address). And given that Auth and Validator have different sessions, I don't see an easy way for them to communicate.

Any suggestions?

DKIM

Hi Ian,

Is there in the pipeline a slimta's version with DKIM support?

Thanks so much!

Run CI on pull requests

I don't know how the CI works, but it seems to me a bit risky to run it only on master and not on pull requests,

@icgood would it be hard to set up ?

Encode messages as quoted printable

Hi Ian!

I´m having an issue with python slimta about message encoding. Unfortunately the most part of antispam like spamassassin understand that messages sent using base64 are classifieds as spam message. We tried to use the method encode_7bit to force to encode the message as quoted_printable but the slimtas insists to send as base64.

There is another way to setup the header to sent the messages as quoted_printable?

Python slimta is sent like bellow

--===============3378800549023565627==
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: base64

JiM4MjAzOyYjODIwMzsNDQpDYXNvIG4mIzIyNztvIGVzdGVqYSB2aXN1YWxpemFuZG8gY29ycmV0
YW1lbnRlIGVzdGEgbWVuc2FnZW0sDQogICAgYWNlc3NlIGFxdWkuDQ0KCQkNDQoJCQkNDQoJCQkJ
CQkNDQoJCQkJCQkNDQoJCQkJCQkNDQoJCQkJCQkNDQoJCQkJCQ0NCgkJCQkJCQ0NCgkJCQkJCSYj
MTYwOw0NCgkJCQkJCQ0NCgkJCQkJCQ0NCgkJCQkJDQ0KCQkJCQkJDQ0KCQkJCQkJDQ0KCQkJCQkJ
CQkJQ2FybmF2YWwgbm8gUmlvIGRlIEphbmVpcm8/DQ0KDQ0KCQkJCQkJCQkJQ09CRVJUVVJBIENP
TVBMRVRBDQ0KDQ0KCQkJCQkJCQkJRU0gJiMxOTM7UkVBIE5PQlJFIERFIEJPVEFGT0dPDQ0KDQ0K
CQkJCQkJCQkJUEFSQSBHUlVQT1MgREUgNiBQRVNTT0FTJiMxNjA7DQ0KDQ0KCQkJCQkJCQkJUGVy
dG8gZG9zIE1FTEhPUkVTIEJMT0NPUyBkZSBjYXJuYXZhbCAhDQ0KCQkJCQkJCQkJDQ0KCQkJCQkJ
CQkNDQoJCQkJCQkJCQlBcGFydGFtZW50byB0b2RvIHJlZm9ybWFkbywgbnVuY2EgYWx1Z2Fkbywg
cGVydG8gZGUgdHVkby4NDQoNDQoJCQkJCQkJCQlQYXJhIGF0JiMyMzM7IDggcGVzc29hcy4gUGVy
ZmVpdG8gcGFyYSA2IHBlc3NvYXMuDQ0KCQkJCQkJCQkJDQ0KCQkJCQkJCQkNDQoJCQkJCQkNDQoJ
CQkJCQ0NCgkJCQkJCSYjMTYwOyYjMTYwOw0NCgkJCQkJCQ0NCgkJCQkJCQkJCSYjMTYwOw0NCg0N
CgkJCQkJCQkJCQ0NCg0NCgkJCQkJCQkJCSYjMTYwOw0NCg0NCgkJCQkJCQkJCSYjMTYwOw0NCgkJ
CQkJCQkJCQ0NCgkJCQkJCQkJCQ0NCgkJCQkJCQkJCURlc2NyaSYjMjMxOyYjMjI3O28gZG8gaW0m
IzI0Mzt2ZWw6DQ0KDQ0KCQkJCQkJCQkJQW1wbG8gMiBRdWFydG9zIHBhcmEgYWNvbW9kYXIgNiBw
ZXNzb2FzIGNvbmZvcnRhdmVsbWVudGUgLiBUb2RvcyBvcyBjJiMyNDQ7bW9kb3MgY29tIEFyLSBj
b25kaWNpb25hZG8uIFNlciYjMjI1OyBhIHByaW1laXJhIGxvY2EmIzIzMTsmIzIyNztvIGFwJiMy
NDM7cyBvYnJhIGRlIHJlZm9ybWEuIEltcGVjJiMyMjU7dmVsLiBWaXN0YSBwYW5vciYjMjI2O21p
Y2EgcGFyYSBQJiMyMjc7byBkZSBBJiMyMzE7JiMyNTA7Y2FyIGUgQmEmIzIzNzthIGRlIEd1YW5h
YmFyYS4gQ0hVUlJBU1FVRUlSQSBFIEhJRFJPTUFTU0FHRU0gZGVudHJvIGRvIGFwYXJ0YW1lbnRv
LiBUZW0gY29tJiMyMzM7cmNpbyBwciYjMjQzO3hpbW8gZSBtZXRyJiMyNDQ7IGUgbyBTaG9wcGlu
ZyBSaW8gU3VsIGVzdCYjMjI1OyBuYXMgcmVkb25kZXphcy4gVGVtIFRWIGEgQ2FibyBlIEludGVy
bmV0IFdpcmVsZXNzLg0NCg0NCgkJCQkJCQkJCUNvbnRhdG8gYWJhaXhvDQ0KCQkJCQkJCQkJDQ0K
CQkJCQkJCQkNDQoJCQkJCQkNDQoJCQkJCQ0NCgkJCQkJCSYjMTYwOw0NCgkJCQkJCQ0NCgkJCQkJ
DQ0KCQkJCQkJDQ0KCQkJCQkJDQ0KCQkJCQkJCQkJDQ0KCQkJCQkJCQkJRmVub21lbmFsOg0NCg0N
CgkJCQkJCQkJCUNvbSBvIG1ldHImIzI0NDsgcXVlIGZpY2EgYSAxMiBtaW51dG9zIGEgcCYjMjMz
Oywgdm9jJiMyMzQ7IHBvZGUgaXIgcGFyYSB2JiMyMjU7cmlhcyBwcmFpYXMgZGlzdGFudGVzIGVt
IHF1ZXN0JiMyMjc7byBkZSBtaW51dG9zLiBDb3BhY2FiYW5hPyAxNzAwIG1ldHJvcyBkbyBhcGFy
dGFtZW50by4gU2UgbiYjMjI3O28gcXVpc2VyIGZhemVyIG5hZGEsIGRlc2ZydXRlIGRhIHNhdW5h
LCBoaWRyb21hc3NhZ2VtIGUgY2h1cnJhc3F1ZWlyYSBkZW50cm8gZG8gc2V1IGFwYXJ0YW1lbnRv
LiBJbXBvc3MmIzIzNzt2ZWwgbiYjMjI3O28gZ29zdGFyIGRlbGUgIQ0NCg0NCgkJCQkJCQkJCSYj
MTYwOw0NCg0NCgkJCQkJCQkJCSYjMTYwO1BhcmEgbWFpb3JlcyBpbmZvcm1hJiMyMzE7JiMyNDU7
ZXMgY29udGF0byBubyByb2RhcCYjMjMzOyBkZXNzYSBwJiMyMjU7Z2luYQ0NCgkJCQkJCQkJCQ0N
CgkJCQkJCQkJDQ0KCQkJCQkJDQ0KCQkJCQkNDQoJCQkJCQkmIzE2MDsNDQoJCQkJCQkNDQoJCQkJ
CQ0NCgkJCQkJCQ0NCgkJCQkJCQ0NCgkJCQkJCQkJCQ0NCgkJCQkJCQkJCUNvbW9kaWRhZGUgZSBD
b25mb3J0bzoNDQoNDQoJCQkJCQkJCQlTYWxhIGJlbSBncmFuZGUsIGNvbSAyIHNvZiYjMjI1O3Mg
ZSB1bSBzb2YmIzIyNTstY2FtYSBiZW0gY29uZm9ydCYjMjI1O3ZlbCwgY29tIGFyLWNvbmRpY2lv
bmFkbyBlIFRWIGEgY2FibyBlbSB0b2RvcyBvcyBhbWJpZW50ZXMuIENvbW9kaWRhZGUsIG5vYnJl
emEgZSBjb25mb3J0byBlbSB1bSBsdWdhciBzJiMyNDM7Lg0NCg0NCgkJCQkJCQkJCVBhcmEgbWFp
b3JlcyBpbmZvcm1hJiMyMzE7JiMyNDU7ZXMgY29udGF0byBubyByb2RhcCYjMjMzOyBkZXNzYSBw
JiMyMjU7Z2luYQ0NCgkJCQkJCQkJCQ0NCgkJCQkJCQkJDQ0KCQkJCQkJDQ0KCQkJCQkNDQoJCQkJ
CQkmIzE2MDsNDQoNDQoJCQkJCQlNQUlTIEZPVE9TPw0NCg0NCgkJCQkJCUNMSVFVRSBBUVVJIEUg
VkVKQSBBUyBGT1RPUw0NCg0NCgkJCQkJCVRlbW9zIG91dHJvcyBhcGFydGFtZW50b3MuDQ0KDQ0K
CQkJCQkJJiMxNjA7DQ0KCQkJCQkJDQ0KCQkJCQkNDQoJCQkJCQkNDQoJCQkJCQkNDQoJCQkJCQkJ
CQlNb3JhZGlhIENhcmlvY2ENDQoNDQoJCQkJCQkJCQlSRVNFUlZBUzogY29udGF0b0Btb3JhZGlh
Y2FyaW9jYS5jb20uYnINDQoNDQoJCQkJCQkJCQkmIzE2MDsNDQoNDQoJCQkJCQkJCQkNDQoJCQkJ
CQkJCQkNDQoJCQkJCQkJCQkJCQlHdXN0YXZvIENhcmFtJiMxNjA7DQ0KCQkJCQkJCQkJCQkJCQkJ
KDIxKSAyNTc3OTY5NyAoRml4bykNDQoJCQkJCQkJCQkJCQkJCSgyMSkgOTkzNjY3MDQwIChPaSkN
DQoJCQkJCQkJCQkJCQkJCQkoMjEpIDk2NTUzMjIxMSAoVGltKQ0NCgkJCQkJCQkJCQkJCQkJKDIx
KSA5OTEwOTUxMjEgKENsYXJvKQ0NCgkJCQkJCQkJCQkJCQkJCSgyMSkgOTk1NDg3MTExIChWaXZv
KQ0NCgkJCQkJCQkJCQkJCQkJDQ0KCQkJCQkJCQkJCQkmIzE2MDsNDQoJCQkJCQkJCQkNDQoJCQkJ
CQkJCQkNDQoJCQkJCQkJCQ0NCgkJCQkJCQ0NCgkJCQkJDQ0KCQlFc3RlIGUtbWFpbCBmb2kgZW52
aWFkbyBwYXJhIGd1c3Rhdm8uY2FyYW1AbWFpbGVyd2ViLmNvbS5ici4gDQogICAgU2Ugdm9jJiMy
MzQ7IG4mIzIyNztvIGRlc2VqYSBtYWlzIHJlY2ViZXIgbm9zc29zIGUtbWFpbHMsICBjYW5jZWxl
IHN1YSBpbnNjcmkmIzIzMTsmIzIyNztvIGFxdWkuDQ0KCQkmIzE2MDsNDQoNDQomIzE2MDs=

--===============3378800549023565627==
Content-Type: text/html; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: base64

PGh0bWw+PGhlYWQ+PG1ldGEgY29udGVudD0idGV4dC9odG1sOyBjaGFyc2V0PVVURi04IiBodHRw
LWVxdWl2PSJDb250ZW50LVR5cGUiPjx0aXRsZT48L3RpdGxlPjwvaGVhZD48Ym9keT48aW1nIHNy
Yz0iaHR0cHM6Ly9wYWluZWwubWFpbGVyd2ViLmNvbS5ici9jYW1wYWlnbnMvY2FtcGFpZ24vZmxh
Zy81MmE5MDk1NzcwY2JhOTY3MjE0NjRlOTdfMTIwNy5naWYiIHdpZHRoPSIxIiBoZWlnaHQ9IjEi
PjxwPiYjODIwMzsmIzgyMDM7PC9wPg0NCjxtZXRhIGNvbnRlbnQ9ImVuLXVzIiBodHRwLWVxdWl2
PSJDb250ZW50LUxhbmd1YWdlIj48dGFibGUgYWxpZ249ImNlbnRlciIgYm9yZGVyPSIwIiBjZWxs
cGFkZGluZz0iMCIgY2VsbHNwYWNpbmc9IjAiIHdpZHRoPSI2NTAiPjx0Ym9keT48dHI+PHRkIGFs
aWduPSJjZW50ZXIiIHN0eWxlPSJmb250LWZhbWlseTpBcmlhbCwgVmVyZGFuYSwgR2VuZXZhLCBz
YW5zLXNlcmlmOyBmb250LXNpemU6OXB4OyBwYWRkaW5nOjEwcHggMCAxMHB4IDA7IGNvbG9yOiMz
MzMiPkNhc28gbiYjMjI3O28gZXN0ZWphIHZpc3VhbGl6YW5kbyBjb3JyZXRhbWVudGUgZXN0YSBt
ZW5zYWdlbSwNCiAgICA8YSBocmVmPSJodHRwczovL3BhaW5lbC5tYWlsZXJ3ZWIuY29tLmJyL3Zp
ZXcvNTJhOTA5NTc3MGNiYTk2NzIxNDY0ZTk3XzEyMDcvIj5hY2Vzc2UgYXF1aS48L2E+PC90ZD4N
DQoJCTwvdHI+PHRyPjwvdHI+PC90Ym9keT48L3RhYmxlPjx0YWJsZSBhbGlnbj0iY2VudGVyIiBi
Z2NvbG9yPSIjZmZmZmZmIiBib3JkZXI9IjAiIGNlbGxwYWRkaW5nPSIwIiBjZWxsc3BhY2luZz0i
MCIgY2xhc3M9Im9oaWVfc29ydGFibGUiIHN0eWxlPSJib3JkZXI6IDFweCBzb2xpZCAjYzBjMGMw
OyIgd2lkdGg9IjYwMCI+PHRib2R5Pjx0cj48dGQgYWxpZ249ImNlbnRlciIgd2lkdGg9IjEwMCUi
Pg0NCgkJCTx0YWJsZSBhbGlnbj0iY2VudGVyIiBib3JkZXI9IjAiIGNlbGxwYWRkaW5nPSIwIiBj
ZWxsc3BhY2luZz0iMCIgc3R5bGU9IndpZHRoOiA1OTJweDsiIHdpZHRoPSI2MDAiPjx0Ym9keSBj
bGFzcz0iY29udGVudCI+PHRyPjx0ZCBhbGlnbj0iY2VudGVyIiBzdHlsZT0id2lkdGg6IDU4OHB4
OyIgdmFsaWduPSJ0b3AiIHdpZHRoPSIxMDAlIj4NDQoJCQkJCQk8ZGl2IGNsYXNzPSJvaGllX3Nv
cnRFbGVtZW50Ij4NDQoJCQkJCQk8cCBzdHlsZT0ibWFyZ2luLWJvdHRvbTogMHB4OyBtYXJnaW4t
dG9wOiAwcHg7Ij48aW1nIGFsdD0iIiBzcmM9Imh0dHBzOi8vZDNua2Z4NjF3MGhpaHEuY2xvdWRm
cm9udC5uZXQvdXBsb2Fkcy9pbmZvd2lkZS9ndXN0YXZvY2FyYW0vMjAxNC8wMi8xMy9jYXBhLmpw
ZyIgc3R5bGU9IndpZHRoOiA2NTBweDsgaGVpZ2h0OiAyNTBweDsiPjwvcD4NDQoJCQkJCQk8L2Rp
dj4NDQoJCQkJCQk8L3RkPg0NCgkJCQkJPC90cj48dHI+PHRkIGFsaWduPSJjZW50ZXIiIGJhY2tn
cm91bmQ9IkhJRV9UZW1wbGF0ZV85NjVfaTAyLmdpZiIgYmdjb2xvcj0iIzAwMDAwMCIgaGVpZ2h0
PSIzNyIgc3R5bGU9ImZvbnQtc2l6ZTogMTBweDsgaGVpZ2h0OiAzN3B4OyBmb250LWZhbWlseTog
dmVyZGFuYSwgYXJpYWwsIGhlbHZldGljYSwgc2Fucy1zZXJpZjsgY29sb3I6IHJnYigyNTUsIDI1
NSwgMjU1KTsgd2lkdGg6IDU4OHB4OyBiYWNrZ3JvdW5kLXJlcGVhdDogbm8tcmVwZWF0IG5vLXJl
cGVhdDsiIHZhbGlnbj0ibWlkZGxlIiB3aWR0aD0iNjAwIj4NDQoJCQkJCQk8ZGl2IGNsYXNzPSJv
aGllX3NvcnRFbGVtZW50Ij4NDQoJCQkJCQk8cCBzdHlsZT0ibWFyZ2luLWJvdHRvbTogMHB4OyBt
YXJnaW4tdG9wOiAwcHg7Ij4mIzE2MDs8L3A+DQ0KCQkJCQkJPC9kaXY+DQ0KCQkJCQkJPC90ZD4N
DQoJCQkJCTwvdHI+PHRyPjx0ZCBhbGlnbj0iY2VudGVyIiBzdHlsZT0id2lkdGg6IDU4OHB4OyIg
dmFsaWduPSJ0b3AiIHdpZHRoPSIxMDAlIj4NDQoJCQkJCQk8ZGl2IGNsYXNzPSJvaGllX3NvcnRF
bGVtZW50Ij4NDQoJCQkJCQk8dGFibGUgYWxpZ249ImNlbnRlciIgYm9yZGVyPSIwIiBjZWxscGFk
ZGluZz0iMCIgY2VsbHNwYWNpbmc9IjAiIHdpZHRoPSI1NDAiPjx0Ym9keT48dHI+PHRkIGFsaWdu
PSJjZW50ZXIiIHN0eWxlPSJmb250LXNpemU6IDE2cHg7IGZvbnQtZmFtaWx5OiAnY2VudHVyeSBn
b3RoaWMnLCBhcmlhbCwgaGVsdmV0aWNhLCBzYW5zLXNlcmlmOyBib3JkZXItYm90dG9tLWNvbG9y
OiAjYjE4NzRkOyBib3JkZXItYm90dG9tLXdpZHRoOiAxcHg7IGJvcmRlci1ib3R0b20tc3R5bGU6
IHNvbGlkOyBmb250LXdlaWdodDogYm9sZDsgY29sb3I6ICNiMTg3NGQ7IHBhZGRpbmctYm90dG9t
OiA1cHg7IHBhZGRpbmctdG9wOiAxNXB4OyIgd2lkdGg9IjU0MCI+DQ0KCQkJCQkJCQkJPGgxIHN0
eWxlPSJtYXJnaW4tYm90dG9tOiAwcHg7IG1hcmdpbi10b3A6IDBweDsiPjxzcGFuIHN0eWxlPSJj
b2xvcjojMDAwMDAwOyI+PHN0cm9uZz5DYXJuYXZhbCBubyBSaW8gZGUgSmFuZWlybz88L3N0cm9u
Zz48L3NwYW4+PC9oMT4NDQoNDQoJCQkJCQkJCQk8aDEgc3R5bGU9Im1hcmdpbi1ib3R0b206IDBw
eDsgbWFyZ2luLXRvcDogMHB4OyI+PHNwYW4gc3R5bGU9ImNvbG9yOiMwMDAwMDA7Ij48c3Ryb25n
PkNPQkVSVFVSQSBDT01QTEVUQTwvc3Ryb25nPjwvc3Bhbj48L2gxPg0NCg0NCgkJCQkJCQkJCTxo
MSBzdHlsZT0ibWFyZ2luLWJvdHRvbTogMHB4OyBtYXJnaW4tdG9wOiAwcHg7Ij48c3BhbiBzdHls
ZT0iY29sb3I6IzAwMDAwMDsiPjxzdHJvbmc+RU0gJiMxOTM7UkVBIE5PQlJFIERFIEJPVEFGT0dP
PC9zdHJvbmc+PC9zcGFuPjwvaDE+DQ0KDQ0KCQkJCQkJCQkJPGgxIHN0eWxlPSJtYXJnaW4tYm90
dG9tOiAwcHg7IG1hcmdpbi10b3A6IDBweDsiPjxzcGFuIHN0eWxlPSJjb2xvcjojMDAwMDAwOyI+
PHN0cm9uZz48c3BhbiBzdHlsZT0iZm9udC1zaXplOiAxNnB4OyBsaW5lLWhlaWdodDogMS42ZW07
Ij5QQVJBIEdSVVBPUyBERSA2IFBFU1NPQVMmIzE2MDs8L3NwYW4+PC9zdHJvbmc+PC9zcGFuPjwv
aDE+DQ0KDQ0KCQkJCQkJCQkJPGgxIHN0eWxlPSJtYXJnaW4tYm90dG9tOiAwcHg7IG1hcmdpbi10
b3A6IDBweDsiPjxzcGFuIHN0eWxlPSJjb2xvcjojMDAwMDAwOyI+PHN0cm9uZz48c3BhbiBzdHls
ZT0iZm9udC1zaXplOiAxNnB4OyBsaW5lLWhlaWdodDogMS42ZW07Ij5QZXJ0byBkb3MgTUVMSE9S
RVMgQkxPQ09TIGRlIGNhcm5hdmFsICE8L3NwYW4+PC9zdHJvbmc+PC9zcGFuPjwvaDE+DQ0KCQkJ
CQkJCQkJPC90ZD4NDQoJCQkJCQkJCTwvdHI+PHRyPjx0ZCBhbGlnbj0iY2VudGVyIiBzdHlsZT0i
Zm9udC1zaXplOiAxMHB4OyBmb250LWZhbWlseTogdmVyZGFuYSwgYXJpYWwsIGhlbHZldGljYSwg
c2Fucy1zZXJpZjsgY29sb3I6ICMwMDAwMDA7IHBhZGRpbmctYm90dG9tOiAxMHB4OyBwYWRkaW5n
LXRvcDogNXB4OyBsaW5lLWhlaWdodDogMTVweDsiIHdpZHRoPSI1NDAiPg0NCgkJCQkJCQkJCTxo
MiBzdHlsZT0ibWFyZ2luLWJvdHRvbTogMHB4OyBtYXJnaW4tdG9wOiAwcHg7Ij48c3BhbiBzdHls
ZT0iY29sb3I6IHJnYigxNTMsIDE1MywgMTUzKTsgZm9udC1mYW1pbHk6IEFyaWFsLCBzYW5zLXNl
cmlmOyBmb250LXNpemU6IDE4cHg7IGZvbnQtd2VpZ2h0OiBib2xkOyBsaW5lLWhlaWdodDogMjUu
MTg3NXB4OyI+QXBhcnRhbWVudG8gdG9kbyByZWZvcm1hZG8sIG51bmNhIGFsdWdhZG8sIHBlcnRv
IGRlIHR1ZG8uPC9zcGFuPjwvaDI+DQ0KDQ0KCQkJCQkJCQkJPGgyIHN0eWxlPSJtYXJnaW4tYm90
dG9tOiAwcHg7IG1hcmdpbi10b3A6IDBweDsiPjxzcGFuIHN0eWxlPSJjb2xvcjogcmdiKDE1Mywg
MTUzLCAxNTMpOyBmb250LWZhbWlseTogQXJpYWwsIHNhbnMtc2VyaWY7IGZvbnQtc2l6ZTogMThw
eDsgZm9udC13ZWlnaHQ6IGJvbGQ7IGxpbmUtaGVpZ2h0OiAyNS4xODc1cHg7Ij5QYXJhIGF0JiMy
MzM7IDggcGVzc29hcy4gUGVyZmVpdG8gcGFyYSA2IHBlc3NvYXMuPC9zcGFuPjwvaDI+DQ0KCQkJ
CQkJCQkJPC90ZD4NDQoJCQkJCQkJCTwvdHI+PC90Ym9keT48L3RhYmxlPjwvZGl2Pg0NCgkJCQkJ
CTwvdGQ+DQ0KCQkJCQk8L3RyPjx0cj48dGQgYWxpZ249ImNlbnRlciIgc3R5bGU9IndpZHRoOiA1
ODhweDsiIHZhbGlnbj0idG9wIiB3aWR0aD0iMTAwJSI+DQ0KCQkJCQkJPGRpdiBjbGFzcz0ib2hp
ZV9zb3J0RWxlbWVudCI+JiMxNjA7JiMxNjA7DQ0KCQkJCQkJPHRhYmxlIGFsaWduPSJjZW50ZXIi
IGJvcmRlcj0iMCIgY2VsbHBhZGRpbmc9IjAiIGNlbGxzcGFjaW5nPSIwIiB3aWR0aD0iNTY1Ij48
dGJvZHk+PHRyPjx0ZCBhbGlnbj0ibGVmdCIgc3R5bGU9IndpZHRoOiAxNzFweDsiIHZhbGlnbj0i
dG9wIiB3aWR0aD0iMjQwIj4NDQoJCQkJCQkJCQk8cCBzdHlsZT0ibWFyZ2luLWJvdHRvbTogMHB4
OyBtYXJnaW4tdG9wOiAwcHg7IHRleHQtYWxpZ246IGNlbnRlcjsiPiYjMTYwOzwvcD4NDQoNDQoJ
CQkJCQkJCQk8cCBzdHlsZT0ibWFyZ2luLWJvdHRvbTogMHB4OyBtYXJnaW4tdG9wOiAwcHg7Ij48
aW1nIGFsdD0iIiBzcmM9Imh0dHA6Ly9zMjUucG9zdGltZy5vcmcvYTQ5MHZ5eHYzL0RTQzA3NTY4
LmpwZyIgc3R5bGU9IndpZHRoOiAzMDBweDsgaGVpZ2h0OiAyMjVweDsiPjwvcD4NDQoNDQoJCQkJ
CQkJCQk8cCBzdHlsZT0ibWFyZ2luLWJvdHRvbTogMHB4OyBtYXJnaW4tdG9wOiAwcHg7Ij4mIzE2
MDs8L3A+DQ0KDQ0KCQkJCQkJCQkJPHAgc3R5bGU9Im1hcmdpbi1ib3R0b206IDBweDsgbWFyZ2lu
LXRvcDogMHB4OyI+JiMxNjA7PC9wPg0NCgkJCQkJCQkJCTwvdGQ+DQ0KCQkJCQkJCQkJPHRkIGFs
aWduPSJsZWZ0IiBzdHlsZT0iY29sb3I6IHJnYigxNCwgNDYsIDcxKTsgcGFkZGluZzogNXB4IDEw
cHg7IHdpZHRoOiAzNjhweDsiIHZhbGlnbj0ibWlkZGxlIiB3aWR0aD0iMzI1Ij4NDQoJCQkJCQkJ
CQk8cCBzdHlsZT0iZm9udC1mYW1pbHk6ICdjZW50dXJ5IGdvdGhpYycsIGFyaWFsLCBoZWx2ZXRp
Y2EsIHNhbnMtc2VyaWY7IGZvbnQtc2l6ZTogMTRweDsgbGluZS1oZWlnaHQ6IDE2cHg7IG1hcmdp
bi1ib3R0b206IDEwcHg7IGZvbnQtd2VpZ2h0OiBib2xkOyBjb2xvcjogcmdiKDE3NywgMTM1LCA3
Nyk7IG1hcmdpbi10b3A6IDBweDsiPkRlc2NyaSYjMjMxOyYjMjI3O28gZG8gaW0mIzI0Mzt2ZWw6
PC9wPg0NCg0NCgkJCQkJCQkJCTxwIHN0eWxlPSJmb250LWZhbWlseTogQXJpYWwsIHNhbnMtc2Vy
aWY7IGZvbnQtc2l6ZTogMTRweDsgbGluZS1oZWlnaHQ6IDE2LjA5Mzc1cHg7IG1hcmdpbjogMHB4
IDBweCAxZW07IHBhZGRpbmc6IDBweDsgdGV4dC1hbGlnbjoganVzdGlmeTsiPjxzcGFuIHN0eWxl
PSJjb2xvcjogcmdiKDM0LCAzNCwgMzQpOyBmb250LWZhbWlseTogYXJpYWwsIHNhbnMtc2VyaWY7
IGxpbmUtaGVpZ2h0OiBub3JtYWw7Ij5BbXBsbyAyIFF1YXJ0b3MgcGFyYSBhY29tb2RhciA2IHBl
c3NvYXMgY29uZm9ydGF2ZWxtZW50ZSAuIFRvZG9zIG9zIGMmIzI0NDttb2RvcyBjb20gQXItIGNv
bmRpY2lvbmFkby4gU2VyJiMyMjU7IGEgcHJpbWVpcmEgbG9jYSYjMjMxOyYjMjI3O28gYXAmIzI0
MztzIG9icmEgZGUgcmVmb3JtYS4gSW1wZWMmIzIyNTt2ZWwuIFZpc3RhIHBhbm9yJiMyMjY7bWlj
YSBwYXJhIFAmIzIyNztvIGRlIEEmIzIzMTsmIzI1MDtjYXIgZSBCYSYjMjM3O2EgZGUgR3VhbmFi
YXJhLiBDSFVSUkFTUVVFSVJBIEUgSElEUk9NQVNTQUdFTSBkZW50cm8gZG8gYXBhcnRhbWVudG8u
IFRlbSBjb20mIzIzMztyY2lvIHByJiMyNDM7eGltbyBlIG1ldHImIzI0NDsgZSBvIFNob3BwaW5n
IFJpbyBTdWwgZXN0JiMyMjU7IG5hcyByZWRvbmRlemFzLiBUZW0gVFYgYSBDYWJvIGUgSW50ZXJu
ZXQgV2lyZWxlc3MuPC9zcGFuPjwvcD4NDQoNDQoJCQkJCQkJCQk8cCBzdHlsZT0iZm9udC1mYW1p
bHk6IEFyaWFsLCBzYW5zLXNlcmlmOyBmb250LXNpemU6IDE0cHg7IGxpbmUtaGVpZ2h0OiAxNi4w
OTM3NXB4OyBtYXJnaW46IDBweCAwcHggMWVtOyBwYWRkaW5nOiAwcHg7IHRleHQtYWxpZ246IGp1
c3RpZnk7Ij48c3Ryb25nPkNvbnRhdG8gYWJhaXhvPC9zdHJvbmc+PC9wPg0NCgkJCQkJCQkJCTwv
dGQ+DQ0KCQkJCQkJCQk8L3RyPjwvdGJvZHk+PC90YWJsZT48L2Rpdj4NDQoJCQkJCQk8L3RkPg0N
CgkJCQkJPC90cj48dHI+PHRkIGFsaWduPSJjZW50ZXIiIGNvbHNwYW49IjIiIHN0eWxlPSJoZWln
aHQ6IDhweDsgcGFkZGluZzogMTBweCAwcHg7IiB2YWxpZ249Im1pZGRsZSIgd2lkdGg9IjU2NSI+
DQ0KCQkJCQkJPHAgc3R5bGU9Im1hcmdpbi1ib3R0b206IDBweDsgbWFyZ2luLXRvcDogMHB4OyI+
JiMxNjA7PC9wPg0NCgkJCQkJCTwvdGQ+DQ0KCQkJCQk8L3RyPjx0cj48dGQgYWxpZ249ImxlZnQi
IHN0eWxlPSJ3aWR0aDogNTg4cHg7IiB2YWxpZ249InRvcCIgd2lkdGg9IjEwMCUiPg0NCgkJCQkJ
CTxkaXYgY2xhc3M9Im9oaWVfc29ydEVsZW1lbnQiPg0NCgkJCQkJCTx0YWJsZSBhbGlnbj0iY2Vu
dGVyIiBib3JkZXI9IjAiIGNlbGxwYWRkaW5nPSIwIiBjZWxsc3BhY2luZz0iMCIgd2lkdGg9IjU2
NSI+PHRib2R5Pjx0cj48dGQgYWxpZ249ImxlZnQiIHZhbGlnbj0idG9wIiB3aWR0aD0iMjQwIj48
aW1nIGFsdD0iIiBzcmM9Imh0dHA6Ly9zMjUucG9zdGltZy5vcmcvazVkdjVhYXk3L0RTQzA3NTQ5
LmpwZyIgc3R5bGU9IndpZHRoOiAzNTBweDsgaGVpZ2h0OiAyNjJweDsiPjwvdGQ+DQ0KCQkJCQkJ
CQkJPHRkIGFsaWduPSJsZWZ0IiBzdHlsZT0iZm9udC1zaXplOiAxMHB4OyBmb250LWZhbWlseTog
dmVyZGFuYSwgYXJpYWwsIGhlbHZldGljYSwgc2Fucy1zZXJpZjsgY29sb3I6ICMwZTJlNDc7IHBh
ZGRpbmc6IDVweCAxMHB4OyBsaW5lLWhlaWdodDogMTZweDsiIHZhbGlnbj0ibWlkZGxlIiB3aWR0
aD0iMzI1Ij4NDQoJCQkJCQkJCQk8cCBzdHlsZT0ibWFyZ2luLWJvdHRvbTogMTBweDsgZm9udC1z
aXplOiAxNHB4OyBmb250LWZhbWlseTogJ2NlbnR1cnkgZ290aGljJywgYXJpYWwsIGhlbHZldGlj
YSwgc2Fucy1zZXJpZjsgZm9udC13ZWlnaHQ6IGJvbGQ7IGNvbG9yOiAjYjE4NzRkOyBtYXJnaW4t
dG9wOiAwcHg7Ij5GZW5vbWVuYWw6PC9wPg0NCg0NCgkJCQkJCQkJCTxwIHN0eWxlPSJ0ZXh0LWFs
aWduOiBqdXN0aWZ5OyI+PHNwYW4gc3R5bGU9ImNvbG9yOiByZ2IoMTQsIDQ2LCA3MSk7IGZvbnQt
ZmFtaWx5OiBBcmlhbCwgc2Fucy1zZXJpZjsgZm9udC1zaXplOiAxNHB4OyBsaW5lLWhlaWdodDog
MTYuMDkzNzVweDsiPkNvbSBvIG1ldHImIzI0NDsgcXVlIGZpY2EgYSAxMiBtaW51dG9zIGEgcCYj
MjMzOywgdm9jJiMyMzQ7IHBvZGUgaXIgcGFyYSB2JiMyMjU7cmlhcyBwcmFpYXMgZGlzdGFudGVz
IGVtIHF1ZXN0JiMyMjc7byBkZSBtaW51dG9zLiBDb3BhY2FiYW5hPyAxNzAwIG1ldHJvcyBkbyBh
cGFydGFtZW50by4gU2UgbiYjMjI3O28gcXVpc2VyIGZhemVyIG5hZGEsIGRlc2ZydXRlIGRhIHNh
dW5hLCBoaWRyb21hc3NhZ2VtIGUgY2h1cnJhc3F1ZWlyYSBkZW50cm8gZG8gc2V1IGFwYXJ0YW1l
bnRvLiBJbXBvc3MmIzIzNzt2ZWwgbiYjMjI3O28gZ29zdGFyIGRlbGUgITwvc3Bhbj48L3A+DQ0K
DQ0KCQkJCQkJCQkJPHAgc3R5bGU9InRleHQtYWxpZ246IGp1c3RpZnk7Ij4mIzE2MDs8L3A+DQ0K
DQ0KCQkJCQkJCQkJPHAgc3R5bGU9InRleHQtYWxpZ246IGp1c3RpZnk7Ij48c3BhbiBzdHlsZT0i
Zm9udC1mYW1pbHk6IEFyaWFsLCBzYW5zLXNlcmlmOyBmb250LXNpemU6IDEzLjYzNjM2MzAyOTQ3
OTk4cHg7IGxpbmUtaGVpZ2h0OiAxNi4wOTM3NXB4OyB0ZXh0LWFsaWduOiBqdXN0aWZ5OyI+JiMx
NjA7PC9zcGFuPjxzdHJvbmcgc3R5bGU9ImZvbnQtZmFtaWx5OiBBcmlhbCwgc2Fucy1zZXJpZjsg
Zm9udC1zaXplOiAxNHB4OyBsaW5lLWhlaWdodDogMTYuMDkzNzVweDsiPlBhcmEgbWFpb3JlcyBp
bmZvcm1hJiMyMzE7JiMyNDU7ZXMgY29udGF0byBubyByb2RhcCYjMjMzOyBkZXNzYSBwJiMyMjU7
Z2luYTwvc3Ryb25nPjwvcD4NDQoJCQkJCQkJCQk8L3RkPg0NCgkJCQkJCQkJPC90cj48L3Rib2R5
PjwvdGFibGU+PC9kaXY+DQ0KCQkJCQkJPC90ZD4NDQoJCQkJCTwvdHI+PHRyPjx0ZCBhbGlnbj0i
Y2VudGVyIiBjb2xzcGFuPSIyIiBzdHlsZT0icGFkZGluZzogMTBweCAwcHg7IiB2YWxpZ249Im1p
ZGRsZSIgd2lkdGg9IjU2NSI+DQ0KCQkJCQkJPHAgc3R5bGU9Im1hcmdpbi1ib3R0b206IDBweDsg
bWFyZ2luLXRvcDogMHB4OyI+JiMxNjA7PC9wPg0NCgkJCQkJCTwvdGQ+DQ0KCQkJCQk8L3RyPjx0
cj48dGQgYWxpZ249ImxlZnQiIGJvcmRlcj0iMCIgc3R5bGU9IndpZHRoOiA1ODhweDsiIHZhbGln
bj0idG9wIiB3aWR0aD0iMTAwJSI+DQ0KCQkJCQkJPGRpdiBjbGFzcz0ib2hpZV9zb3J0RWxlbWVu
dCI+DQ0KCQkJCQkJPHRhYmxlIGFsaWduPSJjZW50ZXIiIGJvcmRlcj0iMCIgY2VsbHBhZGRpbmc9
IjAiIGNlbGxzcGFjaW5nPSIwIiB3aWR0aD0iNTY1Ij48dGJvZHk+PHRyPjx0ZCBhbGlnbj0ibGVm
dCIgdmFsaWduPSJ0b3AiIHdpZHRoPSIyMzYiPjxpbWcgYWx0PSIiIHNyYz0iaHR0cDovL3MyNS5w
b3N0aW1nLm9yZy91cG5zbnZmZnovRFNDMDc1NDIuanBnIiBzdHlsZT0iaGVpZ2h0OiAyMjVweDsg
d2lkdGg6IDMwMHB4OyI+PC90ZD4NDQoJCQkJCQkJCQk8dGQgYWxpZ249ImxlZnQiIHN0eWxlPSJm
b250LXNpemU6IDEwcHg7IGZvbnQtZmFtaWx5OiB2ZXJkYW5hLCBhcmlhbCwgaGVsdmV0aWNhLCBz
YW5zLXNlcmlmOyBjb2xvcjogIzBlMmU0NzsgcGFkZGluZzogNXB4IDEwcHg7IGxpbmUtaGVpZ2h0
OiAxNnB4OyIgdmFsaWduPSJtaWRkbGUiIHdpZHRoPSIzMjUiPg0NCgkJCQkJCQkJCTxwIHN0eWxl
PSJtYXJnaW4tYm90dG9tOiAxMHB4OyBmb250LXNpemU6IDE0cHg7IGZvbnQtZmFtaWx5OiAnY2Vu
dHVyeSBnb3RoaWMnLCBhcmlhbCwgaGVsdmV0aWNhLCBzYW5zLXNlcmlmOyBmb250LXdlaWdodDog
Ym9sZDsgY29sb3I6ICNiMTg3NGQ7IG1hcmdpbi10b3A6IDBweDsiPkNvbW9kaWRhZGUgZSBDb25m
b3J0bzo8L3A+DQ0KDQ0KCQkJCQkJCQkJPHAgc3R5bGU9Im1hcmdpbi1ib3R0b206IDEwcHg7IG1h
cmdpbi10b3A6IDBweDsiPjxzcGFuIHN0eWxlPSJmb250LWZhbWlseTogQXJpYWwsIHNhbnMtc2Vy
aWY7IGZvbnQtc2l6ZTogMTMuNjM2MzYzMDI5NDc5OThweDsgbGluZS1oZWlnaHQ6IDE2LjA5Mzc1
cHg7Ij5TYWxhIGJlbSBncmFuZGUsIGNvbSAyIHNvZiYjMjI1O3MgZSB1bSBzb2YmIzIyNTstY2Ft
YSBiZW0gY29uZm9ydCYjMjI1O3ZlbCwgY29tIGFyLWNvbmRpY2lvbmFkbyBlIFRWIGEgY2FibyBl
bSB0b2RvcyBvcyBhbWJpZW50ZXMuIENvbW9kaWRhZGUsIG5vYnJlemEgZSBjb25mb3J0byBlbSB1
bSBsdWdhciBzJiMyNDM7Ljwvc3Bhbj48L3A+DQ0KDQ0KCQkJCQkJCQkJPHAgc3R5bGU9Im1hcmdp
bi1ib3R0b206IDBweDsgZm9udC13ZWlnaHQ6IGJvbGQ7IG1hcmdpbi10b3A6IDBweDsiPjxzdHJv
bmcgc3R5bGU9ImNvbG9yOiByZ2IoMTQsIDQ2LCA3MSk7IGZvbnQtZmFtaWx5OiBBcmlhbCwgc2Fu
cy1zZXJpZjsgZm9udC1zaXplOiAxNHB4OyBsaW5lLWhlaWdodDogMTYuMDkzNzVweDsgdGV4dC1h
bGlnbjoganVzdGlmeTsiPlBhcmEgbWFpb3JlcyBpbmZvcm1hJiMyMzE7JiMyNDU7ZXMgY29udGF0
byBubyByb2RhcCYjMjMzOyBkZXNzYSBwJiMyMjU7Z2luYTwvc3Ryb25nPjwvcD4NDQoJCQkJCQkJ
CQk8L3RkPg0NCgkJCQkJCQkJPC90cj48L3Rib2R5PjwvdGFibGU+PC9kaXY+DQ0KCQkJCQkJPC90
ZD4NDQoJCQkJCTwvdHI+PHRyPjx0ZCBhbGlnbj0iY2VudGVyIiBjb2xzcGFuPSIyIiB2YWxpZ249
Im1pZGRsZSIgd2lkdGg9IjU2NSI+DQ0KCQkJCQkJPHAgc3R5bGU9Im1hcmdpbi1ib3R0b206IDBw
eDsgbWFyZ2luLXRvcDogMHB4OyI+JiMxNjA7PC9wPg0NCg0NCgkJCQkJCTxwIHN0eWxlPSJtYXJn
aW4tYm90dG9tOiAwcHg7IG1hcmdpbi10b3A6IDBweDsiPjxzdHJvbmcgc3R5bGU9ImNvbG9yOiBy
Z2IoMTQsIDQ2LCA3MSk7IGZvbnQtZmFtaWx5OiBBcmlhbCwgc2Fucy1zZXJpZjsgZm9udC1zaXpl
OiAxNHB4OyBsaW5lLWhlaWdodDogMTYuMDkzNzVweDsgdGV4dC1hbGlnbjoganVzdGlmeTsiPk1B
SVMgRk9UT1M/PC9zdHJvbmc+PC9wPg0NCg0NCgkJCQkJCTxwIHN0eWxlPSJtYXJnaW4tYm90dG9t
OiAwcHg7IG1hcmdpbi10b3A6IDBweDsiPjxhIGhyZWY9Imh0dHA6Ly93d3cuYWx1Z3VldGVtcG9y
YWRhLmNvbS5ici9pbW92ZWwvcDM3MTU4NTciPjxzdHJvbmcgc3R5bGU9ImNvbG9yOiByZ2IoMTQs
IDQ2LCA3MSk7IGZvbnQtZmFtaWx5OiBBcmlhbCwgc2Fucy1zZXJpZjsgZm9udC1zaXplOiAxOHB4
OyBsaW5lLWhlaWdodDogMTYuMDkzNzVweDsgdGV4dC1hbGlnbjoganVzdGlmeTsiPkNMSVFVRSBB
UVVJIEUgVkVKQSBBUyBGT1RPUzwvc3Ryb25nPjwvYT48L3A+DQ0KDQ0KCQkJCQkJPHAgc3R5bGU9
Im1hcmdpbi1ib3R0b206IDBweDsgbWFyZ2luLXRvcDogMHB4OyI+PHN0cm9uZyBzdHlsZT0iY29s
b3I6IHJnYigxNCwgNDYsIDcxKTsgZm9udC1mYW1pbHk6IEFyaWFsLCBzYW5zLXNlcmlmOyBmb250
LXNpemU6IDE0cHg7IGxpbmUtaGVpZ2h0OiAxNi4wOTM3NXB4OyB0ZXh0LWFsaWduOiBqdXN0aWZ5
OyI+VGVtb3Mgb3V0cm9zIGFwYXJ0YW1lbnRvcy48L3N0cm9uZz48L3A+DQ0KDQ0KCQkJCQkJPHAg
c3R5bGU9Im1hcmdpbi1ib3R0b206IDBweDsgbWFyZ2luLXRvcDogMHB4OyI+JiMxNjA7PC9wPg0N
CgkJCQkJCTwvdGQ+DQ0KCQkJCQk8L3RyPjx0cj48dGQgYWxpZ249ImNlbnRlciIgYmdjb2xvcj0i
IzAwMDAwMCIgc3R5bGU9IndpZHRoOiA1ODhweDsiIHZhbGlnbj0ibWlkZGxlIj4NDQoJCQkJCQk8
ZGl2IGNsYXNzPSJvaGllX3NvcnRFbGVtZW50Ij4NDQoJCQkJCQk8dGFibGUgYWxpZ249ImNlbnRl
ciIgYm9yZGVyPSIwIiBjZWxscGFkZGluZz0iMCIgY2VsbHNwYWNpbmc9IjAiIHdpZHRoPSI1ODAi
Pjx0Ym9keT48dHI+PHRkIGFsaWduPSJjZW50ZXIiIHN0eWxlPSJmb250LXNpemU6IDExcHg7IHBh
ZGRpbmc6IDEwcHggMTBweCAxMHB4IDBweDsgbGluZS1oZWlnaHQ6IDE4cHg7IiB2YWxpZ249Im1p
ZGRsZSIgd2lkdGg9IjEwMCUiPg0NCgkJCQkJCQkJCTxoMiBzdHlsZT0iY29sb3I6IHJnYigyNTUs
IDI1NSwgMjU1KTsgZm9udC1mYW1pbHk6IHZlcmRhbmE7IGZvbnQtd2VpZ2h0OiBub3JtYWw7IG1h
cmdpbi1ib3R0b206IDBweDsgbWFyZ2luLXRvcDogMHB4OyI+PHNwYW4gc3R5bGU9ImNvbG9yOiNG
RkZGRkY7Ij48c3Ryb25nPjxmb250IGlkPSJ5dWlfM183XzJfMV8xMzgwOTAyMTgwNzg1XzE4OTUi
IHN0eWxlPSJjb2xvcjogcmdiKDI1MCwgMjM1LCAyMTUpOyBmb250LWZhbWlseTogJ0hlbHZldGlj
YSBOZXVlJywgSGVsdmV0aWNhLCBBcmlhbCwgc2Fucy1zZXJpZjsgZm9udC1zaXplOiAyMHB4OyBs
aW5lLWhlaWdodDogbm9ybWFsOyI+TW9yYWRpYSBDYXJpb2NhPC9mb250Pjwvc3Ryb25nPjwvc3Bh
bj48L2gyPg0NCg0NCgkJCQkJCQkJCTxwIHN0eWxlPSJjb2xvcjogcmdiKDI1NSwgMjU1LCAyNTUp
OyBmb250LWZhbWlseTogdmVyZGFuYTsgZm9udC13ZWlnaHQ6IG5vcm1hbDsgbWFyZ2luLWJvdHRv
bTogMHB4OyBtYXJnaW4tdG9wOiAwcHg7Ij48c3BhbiBzdHlsZT0iY29sb3I6I0ZGRkZGRjsiPjxz
dHJvbmc+PGZvbnQgc3R5bGU9ImNvbG9yOiByZ2IoMjUwLCAyMzUsIDIxNSk7IGZvbnQtZmFtaWx5
OiAnSGVsdmV0aWNhIE5ldWUnLCBIZWx2ZXRpY2EsIEFyaWFsLCBzYW5zLXNlcmlmOyBmb250LXNp
emU6IDEycHg7IGxpbmUtaGVpZ2h0OiBub3JtYWw7Ij5SRVNFUlZBUzogY29udGF0b0Btb3JhZGlh
Y2FyaW9jYS5jb20uYnI8L2ZvbnQ+PC9zdHJvbmc+PC9zcGFuPjwvcD4NDQoNDQoJCQkJCQkJCQk8
cCBzdHlsZT0iY29sb3I6IHJnYigyNTUsIDI1NSwgMjU1KTsgZm9udC1mYW1pbHk6IHZlcmRhbmE7
IGZvbnQtd2VpZ2h0OiBub3JtYWw7IG1hcmdpbi1ib3R0b206IDBweDsgbWFyZ2luLXRvcDogMHB4
OyI+JiMxNjA7PC9wPg0NCg0NCgkJCQkJCQkJCTxkaXYgc3R5bGU9ImZvbnQtc2l6ZTogMTJweDsg
bGluZS1oZWlnaHQ6IG5vcm1hbDsiPg0NCgkJCQkJCQkJCTx0YWJsZSBib3JkZXI9IjEiIGNlbGxw
YWRkaW5nPSIxIiBjZWxsc3BhY2luZz0iMSIgc3R5bGU9ImNvbG9yOiByZ2IoMCwgMCwgMCk7IGZv
bnQtZmFtaWx5OiAnVGltZXMgTmV3IFJvbWFuJzsgZm9udC1zaXplOiBtZWRpdW07IGxpbmUtaGVp
Z2h0OiBub3JtYWw7IHdpZHRoOiA1MDBweDsiPjx0Ym9keT48dHI+PHRkIHN0eWxlPSJ0ZXh0LWFs
aWduOiBjZW50ZXI7Ij4NDQoJCQkJCQkJCQkJCQk8dGFibGUgYm9yZGVyPSIxIiBjZWxscGFkZGlu
Zz0iMSIgY2VsbHNwYWNpbmc9IjEiIHN0eWxlPSJsaW5lLWhlaWdodDogbm9ybWFsOyBiYWNrZ3Jv
dW5kLWNvbG9yOiByZ2IoMCwgMCwgMCk7IGNvbG9yOiByZ2IoMCwgMCwgMCk7IGZvbnQtZmFtaWx5
OiAnVGltZXMgTmV3IFJvbWFuJzsgZm9udC1zaXplOiBtZWRpdW07IHdpZHRoOiA1MDBweDsiPjx0
Ym9keT48dHI+PHRkIHN0eWxlPSJ0ZXh0LWFsaWduOiBjZW50ZXI7Ij48c3BhbiBzdHlsZT0iY29s
b3I6I0ZGRkZGRjsiPjxiIGlkPSJ5dWlfM183XzJfMV8xMzgwOTAyMTgwNzg1XzE4OTIiIHN0eWxl
PSJmb250LWZhbWlseTogJ0hlbHZldGljYSBOZXVlJywgSGVsdmV0aWNhLCBBcmlhbCwgc2Fucy1z
ZXJpZjsgZm9udC1zaXplOiAxMnB4OyI+PGZvbnQgZmFjZT0idHJlYnVjaGV0IG1zLCBzYW5zLXNl
cmlmIiBpZD0ieXVpXzNfN18yXzFfMTM4MDkwMjE4MDc4NV8xODkxIj5HdXN0YXZvIENhcmFtJiMx
NjA7PC9mb250PjwvYj48L3NwYW4+PC90ZD4NDQoJCQkJCQkJCQkJCQkJCQk8dGQgc3R5bGU9InRl
eHQtYWxpZ246IGNlbnRlcjsiPjxzcGFuIHN0eWxlPSJjb2xvcjojRkZGRkZGOyI+PGIgc3R5bGU9
ImNvbG9yOiByZ2IoMjU1LCAyNTUsIDI1NSk7IGxpbmUtaGVpZ2h0OiBub3JtYWw7IHRleHQtYWxp
Z246IGNlbnRlcjsgYmFja2dyb3VuZC1jb2xvcjogcmdiKDAsIDAsIDApOyBmb250LWZhbWlseTog
J3RyZWJ1Y2hldCBtcycsIHNhbnMtc2VyaWY7IGZvbnQtc2l6ZTogMTJweDsiPjxzcGFuIHN0eWxl
PSJiYWNrZ3JvdW5kLWNvbG9yOiMwMDAwMDA7Ij4oMjEpIDI1Nzc5Njk3IChGaXhvKTwvc3Bhbj48
L2I+PC9zcGFuPjwvdGQ+DQ0KCQkJCQkJCQkJCQkJCQk8L3RyPjx0cj48dGQgc3R5bGU9InRleHQt
YWxpZ246IGNlbnRlcjsiPjxzcGFuIHN0eWxlPSJjb2xvcjojRkZGRkZGOyI+PGIgc3R5bGU9ImZv
bnQtZmFtaWx5OiAnSGVsdmV0aWNhIE5ldWUnLCBIZWx2ZXRpY2EsIEFyaWFsLCBzYW5zLXNlcmlm
OyBmb250LXNpemU6IDEycHg7Ij48Zm9udCBmYWNlPSJ0cmVidWNoZXQgbXMsIHNhbnMtc2VyaWYi
PigyMSkgOTkzNjY3MDQwIChPaSk8L2ZvbnQ+PC9iPjwvc3Bhbj48L3RkPg0NCgkJCQkJCQkJCQkJ
CQkJCTx0ZCBzdHlsZT0idGV4dC1hbGlnbjogY2VudGVyOyI+PHNwYW4gc3R5bGU9ImNvbG9yOiNG
RkZGRkY7Ij48YiBzdHlsZT0iZm9udC1mYW1pbHk6ICd0cmVidWNoZXQgbXMnLCBzYW5zLXNlcmlm
OyBmb250LXNpemU6IDEycHg7Ij4oMjEpIDk2NTUzMjIxMSAoVGltKTwvYj48L3NwYW4+PC90ZD4N
DQoJCQkJCQkJCQkJCQkJCTwvdHI+PHRyPjx0ZCBzdHlsZT0idGV4dC1hbGlnbjogY2VudGVyOyI+
PHNwYW4gc3R5bGU9ImNvbG9yOiNGRkZGRkY7Ij48YiBpZD0ieXVpXzNfN18yXzFfMTM4MDkwMjE4
MDc4NV8xODkyIiBzdHlsZT0iZm9udC1mYW1pbHk6ICdIZWx2ZXRpY2EgTmV1ZScsIEhlbHZldGlj
YSwgQXJpYWwsIHNhbnMtc2VyaWY7IGZvbnQtc2l6ZTogMTJweDsiPjxmb250IGZhY2U9InRyZWJ1
Y2hldCBtcywgc2Fucy1zZXJpZiIgaWQ9Inl1aV8zXzdfMl8xXzEzODA5MDIxODA3ODVfMTg5MSI+
KDIxKSA5OTEwOTUxMjEgKENsYXJvKTwvZm9udD48L2I+PC9zcGFuPjwvdGQ+DQ0KCQkJCQkJCQkJ
CQkJCQkJPHRkIHN0eWxlPSJ0ZXh0LWFsaWduOiBjZW50ZXI7Ij48c3BhbiBzdHlsZT0iY29sb3I6
I0ZGRkZGRjsiPjxiIHN0eWxlPSJmb250LWZhbWlseTogJ3RyZWJ1Y2hldCBtcycsIHNhbnMtc2Vy
aWY7IGZvbnQtc2l6ZTogMTJweDsiPigyMSkgOTk1NDg3MTExIChWaXZvKTwvYj48L3NwYW4+PC90
ZD4NDQoJCQkJCQkJCQkJCQkJCTwvdHI+PC90Ym9keT48L3RhYmxlPjwvdGQ+DQ0KCQkJCQkJCQkJ
CQk8L3RyPjwvdGJvZHk+PC90YWJsZT48cD4mIzE2MDs8L3A+DQ0KCQkJCQkJCQkJPC9kaXY+DQ0K
CQkJCQkJCQkJPC90ZD4NDQoJCQkJCQkJCTwvdHI+PC90Ym9keT48L3RhYmxlPjwvZGl2Pg0NCgkJ
CQkJCTwvdGQ+DQ0KCQkJCQk8L3RyPjwvdGJvZHk+PC90YWJsZT48L3RkPg0NCgkJPC90cj48L3Ri
b2R5PjwvdGFibGU+PHRhYmxlIGFsaWduPSJjZW50ZXIiIGJvcmRlcj0iMCIgY2VsbHBhZGRpbmc9
IjAiIGNlbGxzcGFjaW5nPSIwIiB3aWR0aD0iNjUwIj48dGJvZHk+PHRyPjwvdHI+PHRyPjx0ZCBh
bGlnbj0iY2VudGVyIiBzdHlsZT0iZm9udC1mYW1pbHk6QXJpYWwsIFZlcmRhbmEsIEdlbmV2YSwg
c2Fucy1zZXJpZjsgZm9udC1zaXplOjlweDsgcGFkZGluZzoxMHB4IDAgMTBweCAwOyBjb2xvcjoj
MzMzIj5Fc3RlIGUtbWFpbCBmb2kgZW52aWFkbyBwYXJhIDxhIGhyZWY9Im1haWx0bzpndXN0YXZv
LmNhcmFtQG1haWxlcndlYi5jb20uYnIiPmd1c3Rhdm8uY2FyYW1AbWFpbGVyd2ViLmNvbS5icjwv
YT4uIA0KICAgIFNlIHZvYyYjMjM0OyBuJiMyMjc7byBkZXNlamEgbWFpcyByZWNlYmVyIG5vc3Nv
cyBlLW1haWxzLCA8YSBocmVmPSJodHRwczovL3BhaW5lbC5tYWlsZXJ3ZWIuY29tLmJyL2NvbnRh
Y3RzL2NvbnRhY3Qvb3B0X291dC81MmE5MDk1NzcwY2JhOTY3MjE0NjRlOTdfMTIwNy8iPiBjYW5j
ZWxlIHN1YSBpbnNjcmkmIzIzMTsmIzIyNztvIGFxdWkuPC9hPjwvdGQ+DQ0KCQk8L3RyPjwvdGJ
ZHk+PC90YWJsZT48cD4mIzE2MDs8L3A+DQ0KDQ0KPHA+JiMxNjA7PC9wPjwvYm9keT48L2h0bWw+

--===============3378800549023565627==--

We want that slimta sends like this

This is a multipart message in MIME format.

------=_NextPart_000_4E1D_01CF2CC1.A3704D30
Content-Type: text/plain;
    charset="utf-8"
Content-Transfer-Encoding: quoted-printable

N=C3=A3o sei quem testou, mas chegou no Gmail e no Hotmail na entrada

=20

Oi, LuisAntonio.net, Bol, Netfly, etc na caixa de entrada

=20

=20

=20

De: MailerWeb [mailto:[email protected]] Em nome =
de MailerWeb
Enviada em: ter=C3=A7a-feira, 18 de fevereiro de 2014 12:32
Para: Hotmail
Assunto: Ficou mais f=C3=A1cil falar com os clientes

=20


  =
<https://painel.mailerweb.com.br/campaigns/campaign/flag/522d4f0670cba96b=
62e72db5_1208.gif> Caso n=C3=A3o esteja visualizando corretamente esta =
mensagem, acesse aqui. =
<https://painel.mailerweb.com.br/view/522d4f0670cba96b62e72db5_1208/>=20

=09

 <http://www.mailerweb.com.br/> Mailerweb


 <http://www.mailerweb.com.br/> Ficou f=C3=A1cil voc=C3=AA falar com =
seus clientes! T=C3=A1 esperando o qu=C3=AA? Voc=C3=AA n=C3=A3o tem nada =
a perder. =C3=89 de gra=C3=A7a!


 <http://www.mailerweb.com.br/> Clique aqui e assine gr=C3=A1tis


 <http://www.mailerweb.com.br/> Mailerweb =C3=A9 um sistema de email =
marketing completo para envio de campanhas e com recursos integrados =
para uma perfeita an=C3=A1lise de resultados.


 <http://www.mailerweb.com.br/> Veja como =C3=A9 f=C3=A1cil usar o =
Mailerweb. Acesse: www.mailerweb.com.br


Este e-mail foi enviado para [email protected]. Se =
voc=C3=AA n=C3=A3o deseja mais receber nossos e-mails, cancele sua =
inscri=C3=A7=C3=A3o aqui. =
<https://painel.mailerweb.com.br/contacts/contact/opt_out/522d4f0670cba96=
b62e72db5_1208/>=20

=20


------=_NextPart_000_4E1D_01CF2CC1.A3704D30
Content-Type: text/html;
    charset="utf-8"
Content-Transfer-Encoding: quoted-printable

<html xmlns:v=3D"urn:schemas-microsoft-com:vml" =
xmlns:o=3D"urn:schemas-microsoft-com:office:office" =
xmlns:w=3D"urn:schemas-microsoft-com:office:word" =
xmlns:m=3D"http://schemas.microsoft.com/office/2004/12/omml" =
xmlns=3D"http://www.w3.org/TR/REC-html40"><head><meta =
http-equiv=3DContent-Type content=3D"text/html; charset=3Dutf-8"><meta =
name=3DGenerator content=3D"Microsoft Word 14 (filtered medium)"><!--[if =
!mso]><style>v\:* {behavior:url(#default#VML);}
o\:* {behavior:url(#default#VML);}
w\:* {behavior:url(#default#VML);}
.shape {behavior:url(#default#VML);}
</style><![endif]--><style><!--
/* Font Definitions */
@font-face
    {font-family:"Cambria Math";
    panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
    {font-family:Calibri;
    panose-1:2 15 5 2 2 2 4 3 2 4;}
@font-face
    {font-family:Tahoma;
    panose-1:2 11 6 4 3 5 4 4 2 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
    {margin:0cm;
    margin-bottom:.0001pt;
    font-size:12.0pt;
    font-family:"Times New Roman","serif";}
a:link, span.MsoHyperlink
    {mso-style-priority:99;
    color:blue;
    text-decoration:underline;}
a:visited, span.MsoHyperlinkFollowed
    {mso-style-priority:99;
    color:purple;
    text-decoration:underline;}
span.EstiloDeEmail17
    {mso-style-type:personal-reply;
    font-family:"Calibri","sans-serif";
    color:#262626;
    font-weight:normal;
    font-style:normal;}
.MsoChpDefault
    {mso-style-type:export-only;
    font-family:"Calibri","sans-serif";
    mso-fareast-language:EN-US;}
@page WordSection1
    {size:612.0pt 792.0pt;
    margin:70.85pt 3.0cm 70.85pt 3.0cm;}
div.WordSection1
    {page:WordSection1;}
--></style><!--[if gte mso 9]><xml>
<o:shapedefaults v:ext=3D"edit" spidmax=3D"1026" />
</xml><![endif]--><!--[if gte mso 9]><xml>
<o:shapelayout v:ext=3D"edit">
<o:idmap v:ext=3D"edit" data=3D"1" />
</o:shapelayout></xml><![endif]--></head><body lang=3DPT-BR link=3Dblue =
vlink=3Dpurple><div class=3DWordSection1><p class=3DMsoNormal><span =
style=3D'font-size:11.0pt;font-family:"Calibri","sans-serif";color:#26262=
6'>N=C3=A3o sei quem testou, mas chegou no Gmail e no Hotmail na =
entrada<o:p></o:p></span></p><p class=3DMsoNormal><span =
style=3D'font-size:11.0pt;font-family:"Calibri","sans-serif";color:#26262=
6'><o:p>&nbsp;</o:p></span></p><p class=3DMsoNormal><span =
style=3D'font-size:11.0pt;font-family:"Calibri","sans-serif";color:#26262=
6'>Oi, LuisAntonio.net, Bol, Netfly, etc na caixa de =
entrada<o:p></o:p></span></p><p class=3DMsoNormal><span =
style=3D'font-size:11.0pt;font-family:"Calibri","sans-serif";color:#26262=
6'><o:p>&nbsp;</o:p></span></p><p class=3DMsoNormal><span =
style=3D'font-size:11.0pt;font-family:"Calibri","sans-serif";color:#26262=
6'><o:p>&nbsp;</o:p></span></p><p class=3DMsoNormal><span =
style=3D'font-size:11.0pt;font-family:"Calibri","sans-serif";color:#26262=
6'><o:p>&nbsp;</o:p></span></p><p class=3DMsoNormal><b><span =
style=3D'font-size:10.0pt;font-family:"Tahoma","sans-serif"'>De:</span></=
b><span style=3D'font-size:10.0pt;font-family:"Tahoma","sans-serif"'> =
MailerWeb [mailto:[email protected]] <b>Em nome de =
</b>MailerWeb<br><b>Enviada em:</b> ter=C3=A7a-feira, 18 de fevereiro de =
2014 12:32<br><b>Para:</b> Hotmail<br><b>Assunto:</b> Ficou mais =
f=C3=A1cil falar com os clientes<o:p></o:p></span></p><p =
class=3DMsoNormal><o:p>&nbsp;</o:p></p><div align=3Dcenter><table =
class=3DMsoNormalTable border=3D0 cellspacing=3D0 cellpadding=3D0 =
width=3D650 style=3D'width:487.5pt'><tr><td style=3D'padding:7.5pt 0cm =
7.5pt 0cm'><p class=3DMsoNormal align=3Dcenter =
style=3D'text-align:center'><img width=3D1 height=3D1 =
id=3D"_x0000_i1025" =
src=3D"https://painel.mailerweb.com.br/campaigns/campaign/flag/522d4f0670=
cba96b62e72db5_1208.gif"><span =
style=3D'font-size:7.0pt;font-family:"Arial","sans-serif";color:#333333'>=
Caso n=C3=A3o esteja visualizando corretamente esta mensagem, <a =
href=3D"https://painel.mailerweb.com.br/view/522d4f0670cba96b62e72db5_120=
8/">acesse aqui.</a><o:p></o:p></span></p></td></tr><tr><td =
style=3D'padding:0cm 0cm 0cm 0cm'></td></tr><tr><td style=3D'padding:0cm =
0cm 0cm 0cm'><p class=3DMsoNormal><a =
href=3D"http://www.mailerweb.com.br/"><span =
style=3D'text-decoration:none'><img border=3D0 width=3D650 =
id=3D"_x0000_i1026" =
src=3D"http://images.mailerweb.com.br/campanha-15-04-13/img/campanha3-log=
o.jpg" alt=3DMailerweb></span></a><o:p></o:p></p></td></tr><tr><td =
style=3D'padding:0cm 0cm 0cm 0cm'><p class=3DMsoNormal><a =
href=3D"http://www.mailerweb.com.br/"><span =
style=3D'text-decoration:none'><img border=3D0 width=3D649 =
id=3D"_x0000_i1027" =
src=3D"http://images.mailerweb.com.br/campanha-15-04-13/img/campanha3-msg=
.jpg" alt=3D"Ficou f=C3=A1cil voc=C3=AA falar com seus clientes! T=C3=A1 =
esperando o qu=C3=AA? Voc=C3=AA n=C3=A3o tem nada a perder. =C3=89 de =
gra=C3=A7a!"></span></a><o:p></o:p></p></td></tr><tr><td =
style=3D'padding:0cm 0cm 0cm 0cm'><p class=3DMsoNormal><a =
href=3D"http://www.mailerweb.com.br/"><span =
style=3D'text-decoration:none'><img border=3D0 width=3D649 =
id=3D"_x0000_i1028" =
src=3D"http://images.mailerweb.com.br/campanha-15-04-13/img/campanha3-bot=
ao.jpg" alt=3D"Clique aqui e assine =
gr=C3=A1tis"></span></a><o:p></o:p></p></td></tr><tr><td =
style=3D'padding:0cm 0cm 0cm 0cm'><p class=3DMsoNormal><a =
href=3D"http://www.mailerweb.com.br/"><span =
style=3D'text-decoration:none'><img border=3D0 width=3D649 =
id=3D"_x0000_i1029" =
src=3D"http://images.mailerweb.com.br/campanha-15-04-13/img/campanha3-oqe=
.jpg" alt=3D"Mailerweb =C3=A9 um sistema de email marketing completo  =
para envio de campanhas e com recursos integrados para uma perfeita =
an=C3=A1lise de resultados."></span></a><o:p></o:p></p></td></tr><tr><td =
style=3D'padding:0cm 0cm 0cm 0cm'><p class=3DMsoNormal><a =
href=3D"http://www.mailerweb.com.br/"><span =
style=3D'text-decoration:none'><img border=3D0 width=3D649 =
id=3D"_x0000_i1030" =
src=3D"http://images.mailerweb.com.br/campanha-15-04-13/img/campanha3-url=
.jpg" alt=3D"Veja como =C3=A9 f=C3=A1cil usar o Mailerweb. Acesse: =
www.mailerweb.com.br"></span></a><o:p></o:p></p></td></tr><tr><td =
style=3D'padding:7.5pt 0cm 7.5pt 0cm'><p class=3DMsoNormal =
align=3Dcenter style=3D'text-align:center'><span =
style=3D'font-size:7.0pt;font-family:"Arial","sans-serif";color:#333333'>=
Este e-mail foi enviado para <a =
href=3D"mailto:[email protected]">luis_antonio_santos@hotma=
il.com</a>. Se voc=C3=AA n=C3=A3o deseja mais receber nossos e-mails, <a =
href=3D"https://painel.mailerweb.com.br/contacts/contact/opt_out/522d4f06=
70cba96b62e72db5_1208/">cancele sua inscri=C3=A7=C3=A3o =
aqui.</a><o:p></o:p></span></p></td></tr></table></div><p =
class=3DMsoNormal><span =
style=3D'font-size:10.0pt;font-family:"Calibri","sans-serif"'><o:p>&nbsp;=
</o:p></span></p></div></body></html>
------=_NextPart_000_4E1D_01CF2CC1.A3704D30--

Timeout problem

Hi Ian,

I've found another problem on python-slimta, this is about a timeout error like described bellow

Traceback (most recent call last):
  File "/usr/local/lib/python2.7/dist-packages/gevent/greenlet.py", line 327, in run
    result = self._run(*self.args, **self.kwargs)
  File "/usr/local/lib/python2.7/dist-packages/slimta/queue/__init__.py", line 315, in _attempt
    self.relay._attempt(envelope, attempts)
  File "/usr/local/lib/python2.7/dist-packages/slimta/relay/__init__.py", line 86, in _attempt
    return self.attempt(envelope, attempts)
  File "/usr/local/lib/python2.7/dist-packages/slimta/relay/smtp/mx.py", line 213, in attempt
    return relayer.attempt(envelope, attempts)
  File "/usr/local/lib/python2.7/dist-packages/slimta/relay/pool.py", line 93, in attempt
    return result.get()
  File "/usr/local/lib/python2.7/dist-packages/gevent/event.py", line 235, in get
    raise self._exception
Timeout: 10.0 seconds
<Greenlet at 0x168e550: <bound method Queue._attempt of <Queue at 0x14c2870>>('3eff9b8bcfca4b51b7c1f440c10202a4', <Envelope at 0x19ee850, sender=u'52bd00f04bc96314c, 0)> failed with Timeout

Do you have any what it could be?

Thanks so much!

Happy new year!

When gevent.Timeout hits at times, execution seems to drop dead in it's tracks

I'm having a very hard time tracking this one down, as I'm not sure how in the world this is even happening. When a connection times out, this is what happens in the traceback, and my function that was calling $relay.attempt() just stops, even though I have it in a try/except clause. Can you spare any information as to how I can debug this further? I'll of course provide a patch!

[2013-05-03 18:00:18,326: WARNING/MainProcess] Traceback (most recent call last):
[2013-05-03 18:00:18,326: WARNING/MainProcess] File "/opt/emag/.virtualenvs/emag/src/gevent/gevent/greenlet.py", line 333, in run
[2013-05-03 18:00:18,326: WARNING/MainProcess] result = self._run(_self.args, *_self.kwargs)
[2013-05-03 18:00:18,327: WARNING/MainProcess] File "/opt/emag/lib/python-slimta/slimta/relay/smtp/client.py", line 202, in _run
[2013-05-03 18:00:18,327: WARNING/MainProcess] self._connect()
[2013-05-03 18:00:18,327: WARNING/MainProcess] File "/opt/emag/lib/python-slimta/slimta/relay/smtp/client.py", line 76, in _connect
[2013-05-03 18:00:18,327: WARNING/MainProcess] self.socket = self._socket_creator(self.address)
[2013-05-03 18:00:18,327: WARNING/MainProcess] File "/opt/emag/lib/python-slimta/slimta/relay/smtp/client.py", line 69, in _socket_creator
[2013-05-03 18:00:18,327: WARNING/MainProcess] socket = create_connection(address)
[2013-05-03 18:00:18,327: WARNING/MainProcess] File "/opt/emag/.virtualenvs/emag/src/gevent/gevent/socket.py", line 579, in create_connection
[2013-05-03 18:00:18,328: WARNING/MainProcess] sock.connect(sa)
[2013-05-03 18:00:18,328: WARNING/MainProcess] File "/opt/emag/.virtualenvs/emag/src/gevent/gevent/socket.py", line 347, in connect
[2013-05-03 18:00:18,328: WARNING/MainProcess] self._wait(self._write_event)
[2013-05-03 18:00:18,328: WARNING/MainProcess] File "/opt/emag/.virtualenvs/emag/src/gevent/gevent/socket.py", line 298, in _wait
[2013-05-03 18:00:18,328: WARNING/MainProcess] self.hub.wait(watcher)
[2013-05-03 18:00:18,328: WARNING/MainProcess] File "/opt/emag/.virtualenvs/emag/src/gevent/gevent/hub.py", line 341, in wait
[2013-05-03 18:00:18,329: WARNING/MainProcess] result = waiter.get()
[2013-05-03 18:00:18,329: WARNING/MainProcess] File "/opt/emag/.virtualenvs/emag/src/gevent/gevent/hub.py", line 568, in get
[2013-05-03 18:00:18,329: WARNING/MainProcess] return self.hub.switch()
[2013-05-03 18:00:18,329: WARNING/MainProcess] File "/opt/emag/.virtualenvs/emag/src/gevent/gevent/hub.py", line 331, in switch
[2013-05-03 18:00:18,329: WARNING/MainProcess] return greenlet.switch(self)
[2013-05-03 18:00:18,329: WARNING/MainProcess] Timeout: 20.0 seconds

examples/slimta-mail.py is broken

Auth has changed at 7db29ce but it seems that examples/slimta-mail.py got forgotten in the process :)

I tried to fix it quickly but it's not that simple, as there is no simple example to look at (cause this is the simple example :p).

@icgood mind to give a look at fixing it if you get some time ?

Feature request: SmtpRequireAuthenticationValidators class

It looks like if I want to require smtp authentication, I need to subclass SmtpValidators. (I could be wrong about this).

Could slimta provide a validator class that does this by default?

I could try writing this class for you, but you might want to choose the name. And you might be more familiar with all the proper SMTP status codes to return than I am.

I believe this class would need to override handle_mail, handle_rcpt, and handle_data.

Python3 support, why not ?

Hi, simple question to wonder about why Python3 is not supported,

  • is there any blocking reason (like a dependency not being available for python3) ?
  • is it just the fact that it's using some python2-specific idioms ? (which can be fixed in reasonable time, the project being well covered with tests)

Thanks by advance.

Use destination info in bounce messages

The body of generated bounce messages offers template fields to give the source host and port information, but RFC 3464 2.3.5. indicates that the Remote-MTA field should be the destination host and port. Add these as new fields, leaving the existing ones for backwards-compatibility, and update the default bounce templates to use the new fields.

Using environment markers require recent version of setuptools

Good move to introduce env markers in 7f3b733 that's the proper way to do.

Sadly, with setuptools/pip versions from Debian jessie, using env markers fail:

$ mkvirtualenv -p /usr/bin/python3 slimta
(slimta) $ pip install -e git+https://github.com/slimta/python-slimta.git#egg=python_slimta
Obtaining python-slimta from git+https://github.com/slimta/python-slimta.git#egg=python_slimta
  Updating /home/jocelyn/.virtualenvs/yom/src/python-slimta clone
  Running setup.py (path:/home/jocelyn/.virtualenvs/yom/src/python-slimta/setup.py) egg_info for package python-slimta
    error in python-slimta setup command: Invalid environment marker: python_version <  "3.0"
    Complete output from command python setup.py egg_info:
    error in python-slimta setup command: Invalid environment marker: python_version <  "3.0"

That fixes it :

pip install -U setuptools 

But, that makes the installation a two stage process, removing the "simple as pip install" thing.

So IMHO, reverting 7f3b733 is the way, what do you think ?

The other option is to amend README.md mentioning to pip install -U pip

haproxy support for original ip address

Slimta works great with haproxy, but when you need to saturate all CPU cores, you end up starting more inbound processes. Haproxy helps with that, but it also hides the original ip address. There seems to be a PROXY protocol that both postfix and haproxy support, but i haven't made much of it, even after trying it up with wireshark:

http://permalink.gmane.org/gmane.comp.web.haproxy/8881
http://www.haproxy.org/download/1.5/doc/proxy-protocol.txt

Then i found this:
https://pypi.python.org/pypi/pwho/0.1.0

Before i start messing up with this, is there another way of obtaining the original ip address of the sender? I might have overlooked.
Thanks.

Get the queue size from Queue Class

Hi!

I'm trying to get the queue size from Queue Class using the get_info method as bellow:

#queue_storage created by queue_storage = DictStorage()
#queue created by queue = Queue(queue_storage, relay, backoff=exponential_backoff)

info = queue.store.get_info()

But trying to access get_info method an error occur:

AttributeError: 'DictStorage' object has no attribute 'get_info'

So, how is the best way to get size of the queue, where the get_info is not disposed as said the documentation: http://slimta.org/latest/api/slimta.queue.html?highlight=size?

Thanks so much!

Rogério Carrasqueira

Feature request: Authentication for outbound SMTP

I'd like to use python-slimta to route outbound mail via a "smart host". The smart host will, of course, want me to authenticate before it will accept the email I am trying to send. An API to enable me to install a username+password "provider" into an SMTP Relay would be nice. Ideally, the Relay would show the "provider" the outbound email (ie, the envelope), and then the "provider" would provide the username and password the Relay should use to authenticate with the smart host.

Handle NoNameServer error

Hi,

I'm using Slimta and this app is really awesome, but sometimes we have a problem when we request so much queries to the DNS server at AWS EC2. The error is appearing:

[11/06/2013 11:32:20 PM] exception:NoNameservers:unhandled args=() message='' traceback=['Traceback (most recent call last):\n', '  File "/home/myapp/production/web_app/mailerwe
b.sender/src/python-slimta/slimta/queue/__init__.py", line 315, in _attempt\n    self.relay._attempt(envelope, attempts)\n', '  File "/home/myapp/se
nder/src/python-slimta/slimta/relay/__init__.py", line 86, in _attempt\n    return self.attempt(envelope, attempts)\n', '  File "/home/myapp/sender/
src/python-slimta/slimta/relay/smtp/mx.py", line 203, in attempt\n    dest = self.choose_mx(record.get(), attempts)\n', '  File "/home/myapp/sender/
src/python-slimta/slimta/relay/smtp/mx.py", line 73, in get\n    self._records, self._expiration = self._resolve()\n', '  File "/home/myapp/sender/s
rc/python-slimta/slimta/relay/smtp/mx.py", line 98, in _resolve\n    return self._resolve_mx()\n', ...]
Traceback (most recent call last):
  File "/usr/local/lib/python2.7/dist-packages/gevent/greenlet.py", line 390, in run
    result = self._run(*self.args, **self.kwargs)
  File "/home/myapp/sender/src/python-slimta/slimta/queue/__init__.py", line 315, in _attempt
    self.relay._attempt(envelope, attempts)
  File "/home/myapp/sender/src/python-slimta/slimta/relay/__init__.py", line 86, in _attempt
    return self.attempt(envelope, attempts)
  File "/home/myapp/sender/src/python-slimta/slimta/relay/smtp/mx.py", line 203, in attempt
    dest = self.choose_mx(record.get(), attempts)
  File "/home/myapp/sender/src/python-slimta/slimta/relay/smtp/mx.py", line 73, in get
    self._records, self._expiration = self._resolve()
  File "/home/myapp/sender/src/python-slimta/slimta/relay/smtp/mx.py", line 98, in _resolve
    return self._resolve_mx()
  File "/home/myapp/sender/src/python-slimta/slimta/relay/smtp/mx.py", line 85, in _resolve_mx
    answer = dns.resolver.query(self.domain, 'MX')
  File "/usr/local/lib/python2.7/dist-packages/dns/resolver.py", line 974, in query
    raise_on_no_answer, source_port)
  File "/usr/local/lib/python2.7/dist-packages/dns/resolver.py", line 817, in query
    raise NoNameservers
NoNameservers
<Greenlet at 0x4e0eeb0: <bound method Queue._attempt of <Queue at 0x32a3e10>>('a7075c33019e4e028ac6776d9805152a', <Envelope at 0x72a2250, sender=u'527a9d7c70cba9563, 2)> failed with
 NoNameservers 

There is a way to deal with this?

Patch SmtpSession.HAVE_DATA to respond with the result of the handoff

Are you against replacing
reply.message = '2.6.0 Message accepted for delivery with id'
with
reply.message = '2.6.0 Message accepted for delivery with id %s' % results[0][1]?

My queue mechanism replies with a unique transaction id when i succesfully save to it, and i liked to display that in the smtp session.
Besides checking if results[0][1] is not an error or something like that, it's not used elsewhere.
I'm actually using a patched version of HAVE_DATA in production and it seems like a nice feature. I think i saw a reference to this feature somewhere around here, but i don't find it.

Allow custom logic to set outbound EHLO on Relay

Add a callback that is called early in the connection, with its return value being used by the EHLO command.

  • Possibly call twice, before STARTTLS and after?
  • TODO: Figure out information this callback will need passed in.

raising ConnectionLost with Connection was closed prematurely instead of showing real message

If you are mailing an e-mail to yahoo, yahoo may sometimes reply with
421 4.7.0 [TS01] Messages from x.x.x.x temporarily deferred due to user complaints - 4.16.55
during or before greeting, helo/ehlo or at any point, actually. I'd be interested in obtaining that message, because i can take different actions according to the reply. Instead, i just get an
SmtpTransientRelayError and a reply.code='421', reply.message='4.3.0 Connection was closed prematurely'.

Abstract out buffered sockets from smtp module

A text-based buffered socket might be useful. Basically implement BufferedSocket:

  • Read-until byte(s), defaulting to br'\r?\n'
  • Use bytearray?
  • EdgeServerBuffered, which converts replaces socket with buffered_socket
    • The ProxyProtocolV1 mix-in should be re-worked to take advantage if isinstance(socket, BufferedSocket)

Drop support for python 2.6 ?

Open question : does supporting python 2.6 worth the effort ?

I just started hacking around with slimta, and already noticed 2 times python2.6 was not blocking me but made the things a bit less elegant:

  • the use of unittest2 dependency
  • the usage of several context managers in a single call

I know 2.6-> 2.7 is a big usefull version and expect to face other cases. Also, python 2.7 API is quite designed to be easy to build programs running with both python2 and python3 (see #26 ), all major distros have benn on py2.7 for years so, what remains ?

@icgood what do you think ? (open question)

Timeout problem

Hi Ian,

I've found another problem on python-slimta, this is about a timeout error like described bellow

Traceback (most recent call last):
  File "/usr/local/lib/python2.7/dist-packages/gevent/greenlet.py", line 327, in run
    result = self._run(*self.args, **self.kwargs)
  File "/usr/local/lib/python2.7/dist-packages/slimta/queue/__init__.py", line 315, in _attempt
    self.relay._attempt(envelope, attempts)
  File "/usr/local/lib/python2.7/dist-packages/slimta/relay/__init__.py", line 86, in _attempt
    return self.attempt(envelope, attempts)
  File "/usr/local/lib/python2.7/dist-packages/slimta/relay/smtp/mx.py", line 213, in attempt
    return relayer.attempt(envelope, attempts)
  File "/usr/local/lib/python2.7/dist-packages/slimta/relay/pool.py", line 93, in attempt
    return result.get()
  File "/usr/local/lib/python2.7/dist-packages/gevent/event.py", line 235, in get
    raise self._exception
Timeout: 10.0 seconds
<Greenlet at 0x168e550: <bound method Queue._attempt of <Queue at 0x14c2870>>('3eff9b8bcfca4b51b7c1f440c10202a4', <Envelope at 0x19ee850, sender=u'52bd00f04bc96314c, 0)> failed with Timeout

Do you have any what it could be?

Thanks so much!

DBPageNotFoundError: (-30985, 'DB_PAGE_NOTFOUND: Requested page not found')

Hi,

I'm using python-slimta with memory queue and these error has happened some times. Can anyone help?

Traceback (most recent call last):
  File "/usr/local/lib/python2.7/dist-packages/gevent/greenlet.py", line 327, in run
    result = self._run(*self.args, **self.kwargs)
  File "/home/mailerweb/production/web_app/mailerweb.sender/src/slimta/slimta/queue/__init__.py", line 424, in _dequeue
    envelope, attempts = self.store.get(id)
  File "/home/mailerweb/production/web_app/mailerweb.sender/src/slimta/slimta/queue/dict.py", line 94, in get
    return self.env_db[id], meta['attempts']
  File "/usr/lib/python2.7/shelve.py", line 121, in __getitem__
    f = StringIO(self.dict[key])
  File "/usr/lib/python2.7/bsddb/__init__.py", line 270, in __getitem__
    return _DeadlockWrap(lambda: self.db[key])  # self.db[key]
  File "/usr/lib/python2.7/bsddb/dbutils.py", line 68, in DeadlockWrap
    return function(*_args, **_kwargs)
  File "/usr/lib/python2.7/bsddb/__init__.py", line 270, in <lambda>
    return _DeadlockWrap(lambda: self.db[key])  # self.db[key]
DBPageNotFoundError: (-30985, 'DB_PAGE_NOTFOUND: Requested page not found')
<Greenlet at 0x253acd0: <bound method Queue._dequeue of <Queue at 0x253aeb0>>('0f52444a795b4a8d892e9a7e7eed6d20')> failed with DBPageNotFoundError

Any way of closing the socket during a SmtpSession validation?

I can easily set reply.code = '5xx' during any part of the SmtpSession validation, but i would sometimes like to close the socket of the client connecting to my SmtpEdge as well. Is there a easy way to do this? I'm not able to find any reference to the current socket from that scope.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.