Skip to content

Instantly share code, notes, and snippets.

@cinco
Last active July 28, 2023 04:20
Show Gist options
  • Save cinco/1e2efe4d67dc69b2a26704378ef358ae to your computer and use it in GitHub Desktop.
Save cinco/1e2efe4d67dc69b2a26704378ef358ae to your computer and use it in GitHub Desktop.
Postal - Clear Held with python
POSTAL_LOGIN=your-email
POSTAL_PASSWORD=your-pass
POSTAL_URL=http://your-postal-domain
POSTAL_ORGANIZATION=slug-of-your-organization
POSTAL_MAIL_SERVER=slug-of-mail-server
from bs4 import BeautifulSoup
from lxml import html
import requests
import os
# import re
# ---------------------------------
# ----- Environment Variables -----
# ---------------------------------
email_address = os.environ['POSTAL_LOGIN']
password = os.environ['POSTAL_PASSWORD']
postal_url = os.environ['POSTAL_URL']
postal_org = os.environ['POSTAL_ORGANIZATION']
postal_mailserver = os.environ['POSTAL_MAIL_SERVER']
# --------------------------------
# ----- Post Login - Payload -----
# --------------------------------
payload = {
"utf8": "\u2713",
"return_to": "/",
"email_address": email_address,
"password": password,
"commit ": "Login"
}
# ----------------------------------------
# ----- Get Login authenticity_token -----
# ----------------------------------------
s = requests.session()
login_url = postal_url + "/login"
result = s.get(login_url)
tree = html.fromstring(result.text)
authenticity_token = list(set(tree.xpath("//input[@name='authenticity_token']/@value")))[0]
payload.update({"authenticity_token":authenticity_token})
# ---------------------------
# ----- Make Post Login -----
# ---------------------------
result = s.post(
login_url,
data = payload)
if result.status_code == 200:
print ('successfully logged in')
else:
print ('wrong login or password')
mensagens = []
# -----------------------------------------------
# ----- Find, unhold and retry send message -----
# -----------------------------------------------
def unheld_message():
url = postal_url + '/org/' + postal_org + '/servers/' + postal_mailserver + '/messages/held'
while url:
# ----------------
# ----- Find -----
# ----------------
r = s.get(url)
soup = BeautifulSoup(r.text ,"lxml")
try:
url = soup.find('p', {'class': 'simplePagination__next'}).findAll('a', {'class': 'simplePagination__link'})
except:
print("Don't has next page")
url = []
content = r.content
soup = BeautifulSoup(content, features="lxml")
message_id = soup.find_all("a", class_="messageList__link")
for a in message_id:
# ------------------
# ----- Unhold -----
# ------------------
result = s.get(postal_url + a['href'])
tree = html.fromstring(result.text)
csrftoken = list(set(tree.xpath("//html/head/meta[@name='csrf-token']/@content")))[0]
url1 = (postal_url + a['href'] + "/cancel_hold" )
s.post(
url1,
headers={
'X-CSRF-Token': csrftoken
}
)
# ------------------------------
# ----- Retry send message -----
# ------------------------------
result = s.get(postal_url + a['href'])
tree = html.fromstring(result.text)
csrftoken = list(set(tree.xpath("//html/head/meta[@name='csrf-token']/@content")))[0]
url2 = (postal_url + a['href'] + "/retry" )
s.post(
url2,
headers={
'X-CSRF-Token': csrftoken
}
)
import re
url_path = a['href']
pattern = '[^\/]+(?=\/$|$)'
re = re.findall(pattern, url_path)
for msg_id in re:
print("unhold and retry message, url: " + postal_url + '/org/' + postal_org + '/servers/' + postal_mailserver + '/messages/' + msg_id)
# -----------------------------------------------------------
# ----- run again if held page has next page pagination -----
# -----------------------------------------------------------
if url:
url = postal_url + '/org/' + postal_org + '/servers/' + postal_mailserver + '/messages/held'
else:
break
unheld_message()
beautifulsoup4==4.10.0
html==1.13
requests==2.26.0
lxml==4.7.1
@devopsmash
Copy link

Thank you so much @cinco for your script, but it seems that python3 and pip3 aren't like the old html pip package

pip3 install html

# output
Collecting html
  Using cached html-1.16.tar.gz (7.6 kB)
    ERROR: Command errored out with exit status 1:
     command: /usr/bin/python3 -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'/tmp/pip-install-0r2dzhtq/html/setup.py'"'"'; __file__='"'"'/tmp/pip-install-0r2dzhtq/html/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' egg_info --egg-base /tmp/pip-install-0r2dzhtq/html/pip-egg-info
         cwd: /tmp/pip-install-0r2dzhtq/html/
    Complete output (17 lines):
    Traceback (most recent call last):
      File "<string>", line 1, in <module>
      File "/usr/lib/python3/dist-packages/setuptools/__init__.py", line 19, in <module>
        from setuptools.dist import Distribution, Feature
      File "/usr/lib/python3/dist-packages/setuptools/dist.py", line 35, in <module>
        from setuptools.depends import Require
      File "/usr/lib/python3/dist-packages/setuptools/depends.py", line 6, in <module>
        from .py33compat import Bytecode
      File "/usr/lib/python3/dist-packages/setuptools/py33compat.py", line 11, in <module>
        from setuptools.extern.six.moves import html_parser
      File "/usr/lib/python3/dist-packages/setuptools/_vendor/six.py", line 92, in __get__
        result = self._resolve()
      File "/usr/lib/python3/dist-packages/setuptools/_vendor/six.py", line 115, in _resolve
        return _import_module(self.mod)
      File "/usr/lib/python3/dist-packages/setuptools/_vendor/six.py", line 82, in _import_module
        __import__(name)
    ModuleNotFoundError: No module named 'html.parser'; 'html' is not a package
    ----------------------------------------
ERROR: Command errored out with exit status 1: python setup.py egg_info Check the logs for full command output.

So I made a few changes to support python3 and pip3

First, remove html package from the requirements.txt

Second, replace the html on postal-clear_held.py:

# old
from lxml import html

#new
from lxml.html import fromstring
import lxml.html as PARSER

and

# old
html.fromstring

#new
PARSER.fromstring

now you can run it without any issue

@donatid
Copy link

donatid commented Jul 28, 2023

@devopsmash, your solution is working! Anyway, could you add this tool to remove the email queue? I have a large amount of spam and causing the server to freeze.

Thank you

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment