Commit 4a989056 authored by Fredrik Wendt's avatar Fredrik Wendt

initial-ish commit

parents
Pipeline #290 failed with stages
.env
venv/
__pycache__
.idea
What's in this repo?
====================
The first part of this solution is found in https://gitlab.wendt.io/platform/emailgw-wendt-io
That "first part" receives email from Gmail via Cloud Mailin, and publishes that JSON payload base64 encoded to redis.
This repo contains "part two," which consists of:
* a wrapper that SUBSCRIBEs to redis pubsub topic email
* the wrapper looks at the incoming email and determines what to do with it
* if it's from SDO, and it's about grading, then
* `snatcher.py` is executed, which will log in and try to grab assessment grading work
* notify `push.wendt.io` of the grading work snatched
This whole thing is wrapped in a Docker container, set to restart on stop.
Any exception = sys.exit = restart.
There are two manual util tools to manually trigger this whole thing:
* 1 - talks to redis
* 2 - talks to emailgw.wendt.io
Development
-------------
On Mac OS X, to get access to `redis.wendt.vpn`, set up a TCP port forwarder with SSH:
ssh -L 6379:10.20.30.44:6379 water.wendt.io
#!/usr/bin/env bash
# version 201911270815
set -e
function main {
init
prepare
build
setup_networkz
redeploy
notify_redeploy
}
function init {
export COMPOSE_PROJECT_NAME=sdo-grading-job
export COMPOSE_API_VERSION=auto
export PROJECT=$(basename $(dirname "$(readlink -f "$0")"))
export BASE_DIR=$(pwd)
export TARGET_DIR=$BASE_DIR
}
function prepare {
loggit "Preparing build & deployment environment"
# make_clean_target_dir
check_for_upstream_certificates
}
function make_clean_target_dir {
cd $BASE_DIR
if [ -d $TARGET_DIR ] ; then rm -rf $TARGET_DIR ; fi
mkdir -p $TARGET_DIR
}
function build {
loggit "Building"
cd $TARGET_DIR
if [ -f Dockerfile ] ; then
echo "Building base image $COMPOSE_PROJECT_NAME:latest"
docker build --no-cache -t $COMPOSE_PROJECT_NAME:latest -f Dockerfile .
fi
docker-compose pull
docker-compose build
}
function setup_networkz {
loggit "Setting up docker networking"
# no good way of doing this without exit code != 0
set +e
docker network create internetz > /dev/null
docker network ls
set -e
}
function redeploy {
loggit "Deploying"
cd $TARGET_DIR
echo
echo =======================================================================
echo Running docker containers BEFORE
echo -----------------------------------------------------------------------
docker ps
sleep 2
echo -----------------------------------------------------------------------
echo "Starting new containers"
docker-compose down
docker-compose up -d
sleep 5
echo
echo =======================================================================
echo Running docker containers AFTER
echo -----------------------------------------------------------------------
docker ps
sleep 2
echo -----------------------------------------------------------------------
echo
}
function notify_redeploy {
loggit "Sending notification of deploy"
cd $BASE_DIR
GIT_MSG=$(git log -1 --pretty=%B)
MSG="$GIT_MSG $GO_PIPELINE_COUNTER.$GO_STAGE_COUNTER"
curl -m 5 -fsSL https://push.wendt.io/ \
-d "message=$PROJECT redeployed: $MSG" \
-d url=$PUSH_URL || echo "Notification failed"
}
function loggit {
echo ">>>"
echo -n ">>> STEP: "
echo "$@"
echo ">>>"
}
function inject_vpn_ip_into_docker_compose_file {
loggit "Injecting VPN IP into Docker Compose file"
HOST=$(hostname --short)
VPNHOST=${HOST}.wendt.vpn
VPNIP=$(host $VPNHOST | grep address | tail -n 1 | cut -d ' ' -f 4)
if [ -z "$VPNIP" ] ; then
echo "Couldn't resolve $VPNHOST to an IP address"
exit 1
fi
if [ "$HOME" = "/home/ceda" ] ; then
DEBUG=true
fi
if [ "$DEBUG" ] ; then
clear
echo
echo "LOCAL DEVELOPMENT DETECTED"
echo
VPNIP=0.0.0.0
fi
echo -n "Creating build dir: "
BUILD_DIR=build/${COMPOSE_PROJECT_NAME}
mkdir -p $BUILD_DIR
echo "$BUILD_DIR"
echo -n "Prepping source files: "
echo -n "${COMPOSE_PROJECT_NAME} config "
cp -r src/docker/images/ $BUILD_DIR
mkdir -p $BUILD_DIR/build
echo -n "docker-compose.yml "
sed -e "s/__VPNIP__/$VPNIP/" $BASE_DIR/src/docker/runtime/docker-compose.yml.template > $BUILD_DIR/docker-compose.yml
echo "done"
tree $BASE_DIR/$BUILD_DIR
export TARGET_DIR=$BASE_DIR/$BUILD_DIR
}
function check_for_upstream_certificates {
if [ -d upstream/ ] ; then
echo "USING CERTIFICATES FROM UPSTREAM JOB (folder upstream)"
cp -r upstream/certificates/* proxy/certificates/
else
echo "USING CERTIFICATES FROM git REPO - old?"
fi
}
main
version: '3.8'
services:
snatcher:
build:
context: .
dockerfile: docker/Dockerfile
restart: always
FROM mcr.microsoft.com/playwright/python:v1.52.0-noble
WORKDIR /app
CMD ["python3", "wrapper.py"]
# Install system dependencies
RUN apt-get update && apt-get install -y --no-install-recommends python3-venv && rm -rf /var/lib/apt/lists/*
# Create and activate virtual environment
RUN python -m venv /venv
ENV PATH="/venv/bin:$PATH"
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY .env /app/
COPY *.py /app/
LOGIN_USER=some@one.place
LOGIN_PASS=abcDEF123
import base64
import os
import time
import redis
import json
if __name__ == '__main__':
print("Manually causing a run")
host = 'localhost' if os.getenv('PYCHARM_HOSTED') else 'redis.wendt.vpn'
redis_client = redis.Redis(host=host, port=6379, decode_responses=True)
ts = int(time.time())
print(f"Sending {ts}")
data = {
'headers': { 'subject': f'PSFAKE III Grading Required: fake-{ts}'}
}
json_data = json.dumps(data)
base64_data = base64.b64encode(json_data.encode("utf-8"))
redis_client.publish('email', base64_data)
import requests
if __name__ == '__main__':
print("Manually causing a run")
requests.post("https://emailgw.wendt.io/email", json={"test": True})
How to:
```
screen
python3 -m venv venv
source venv/bin/activate
pip install requests python-dotenv
echo "[]" > ids_seen.json
python3 job.py
```
```
checking for new email 2024-04-05T01:00:06.099477
Setting up new connection to gmail.com
found 7 emails
```
IMAP_USER=some@one.here
IMAP_PASS=someTHINGthere
API_46ELKS_USER=ua..........
API_46ELKS_PASS=B3..........
from dotenv import load_dotenv
import email
import imaplib
import json
import os
import time
import datetime
import requests
class Checker:
# Function to fetch emails with a specific label
def __init__(self):
self.api_46elks_user = os.environ['API_46ELKS_USER']
self.api_46elks_pass = os.environ['API_46ELKS_PASS']
self.imap_user = os.environ['IMAP_USER']
self.imap_pass = os.environ['IMAP_PASS']
self.mail = None
def notify_fredrik_via_sms(self, message='Level III Grading Opportunity\n\nGo to https://eco.scrum.org/grading/results'):
print("new grading opportunity")
fields = {
'from': '46702778511',
'to': '46702778511',
'message': message
}
response = requests.post("https://api.46elks.com/a1/SMS", data=fields,
auth=(self.api_46elks_user, self.api_46elks_pass))
try:
if response.json()['status'] == "created":
print("SMS sent")
except ValueError:
print(f"SMS fail: {response.content}")
def check_for_new_email(self):
print(f"checking for new email {datetime.datetime.now().isoformat()}")
if not self.mail:
self.setup_mail_connection()
(typ, [data]) = self.mail.select("\"" + "Scrum.org/Level III Grading" + "\"")
if typ != "OK":
raise Exception(f"Hmm {typ} was not 'OK'")
count = int(data)
print(f"found {count} emails")
if count == 0:
return
# Search for emails in the selected label
result, data = self.mail.search(None, "ALL")
string_of_ids = data[0].decode("ascii", "ignore")
ids = string_of_ids.split()
ids_seen = set()
new_ids = set()
try:
id_data = open("ids_seen.json").read()
ids_seen.update(json.loads(id_data))
except:
pass
for email_id in ids:
result, data = self.mail.fetch(email_id, "(RFC822)")
raw_email = data[0][1]
msg = email.message_from_bytes(raw_email)
msg_id = msg["Message-ID"]
if msg_id in ids_seen:
continue
new_ids.add(msg_id)
if len(new_ids) > 0:
self.notify_fredrik_via_sms()
ids_seen.update(new_ids)
print(f"Saving {ids_seen}")
open("ids_seen.json", "w").write(json.dumps(list(ids_seen)))
self.mail.close()
self.mail.logout()
self.mail = None
def run(self):
error_count = 0
while error_count < 3:
try:
self.check_for_new_email()
error_count = 0
except Exception as e:
print(f"Error: {e}")
try:
self.mail.close()
except:
pass
self.mail = None
error_count += 1
time.sleep(60 * (error_count + 1))
time.sleep(60)
self.notify_fredrik_via_sms('Exiting grading monitoring')
print("3 errors, aborting")
def setup_mail_connection(self):
print("Setting up new connection to gmail.com")
self.mail = imaplib.IMAP4_SSL('imap.gmail.com')
self.mail.login(self.imap_user, self.imap_pass)
if __name__ == '__main__':
load_dotenv()
print("""How to:
screen
python3 -m venv venv
source venv/bin/activate
pip install requests python-dotenv
cp example.env .env
python3 job.py
""")
Checker().run()
pipelines:
sdo-grading-job-snatcher:
group: Professional
materials:
source:
git: ssh://git@gitlab.wendt.vpn:5522/professional/sdo-grading-job-snatcher.git
stages:
- deploy:
resources:
- trumpet
tasks:
- exec:
command: ./deploy.sh
from dotenv import load_dotenv
import logging
import os
import sys
import requests
from playwright.sync_api import sync_playwright
import time
log = None
development_mode = os.getenv('PYCHARM_HOSTED')
load_env()
login_user = os.environ['LOGIN_USER']
login_pass = os.environ['LOGIN_PASS']
def snatch_grading_work(headless=None):
global log
if log is None:
log = logging.getLogger('snatcher')
if headless is None:
headless = False if development_mode else True
log.info(f"Snatching grading work ({headless})")
playwright = sync_playwright().start()
browser = playwright.chromium.launch(headless=headless)
page = browser.new_page()
try:
log.info("Going over to SDO")
page.goto('https://eco.scrum.org/grading/results', wait_until='networkidle', timeout=30000)
# Check for password input and perform login if present
password_input = page.query_selector('input[id="password"]')
if password_input:
log.info("Logging in")
page.fill('input[id="password"]', login_pass)
page.fill('input[id="loginId"]', login_user)
page.click('button:has-text("Log In")')
# Wait for a specific XHR request to complete
with page.expect_response('https://as-sdo-eco-api-prod-eastus.azurewebsites.net/grading/results', timeout=30000) as response_info:
response = response_info.value
log.info(f"XHR request completed with status: {response.status}")
page.wait_for_selector('a:has-text("Grading Queue")', timeout=15000)
page.wait_for_selector('span:has-text("Result ID")', timeout=15000)
time.sleep(2)
# Don't claim if we already have one claimed
unclaim_buttons = page.query_selector_all('span:text-is("Release My Claim")')
unclaim_count = len(unclaim_buttons)
log.info(f"Release My Claim buttons: {unclaim_count}")
if unclaim_count > 1:
log.info("Not claiming yet another test")
else:
log.info("No grading jobs assigned to me, going ahead to snatch a new one")
# Verify the number of "Claim" buttons
claim_buttons = page.query_selector_all('span:text-is("Claim")')
claim_count = len(claim_buttons)
log.info(f"Claim buttons: {claim_count}")
if claim_count == 0:
log.info("No Claim button(s) found - nothing to do")
else:
log.info("Clicking Claim button 0")
claim_buttons[0].click()
# Wait for page to reload and number of "Claim" buttons to reduce by 1
start_time = time.time()
while True:
current_buttons = page.query_selector_all('span:text-is("Claim")')
if len(current_buttons) == claim_count - 1:
break
if time.time() - start_time > 30: # Timeout after 30 seconds
break
time.sleep(0.5) # Poll every 0.5 seconds
log.info(f"Clicked first 'Claim' button; 'Claim' buttons reduced to {claim_count - 1}")
requests.post("https://push.wendt.io", params={"message": "New grading work snatched!"})
except Exception as e:
log.error(f"Error: {e}")
if development_mode:
input("Press Enter to continue...")
browser.close()
playwright.stop()
log.info("Done snatching grading work")
if __name__ == '__main__':
logging.basicConfig(level=logging.INFO, stream=sys.stdout)
snatch_grading_work()
import base64
import datetime
import json
import logging
import os
import redis
import sys
from snatcher import snatch_grading_work
development_mode = os.getenv('PYCHARM_HOSTED')
def main():
log = logging.getLogger('wrapper')
log.info("Running main")
host = 'localhost' if development_mode else 'redis.wendt.vpn'
try:
client = redis.Redis(host=host, port=6379, decode_responses=True)
pubsub = client.pubsub()
pubsub.subscribe('email')
log.info("Subscribed to 'email' topic")
while True:
now = datetime.datetime.now(datetime.timezone.utc).isoformat(sep=' ', timespec='seconds')
log.info(f"Starting to wait for message at {now}")
try:
message = pubsub.get_message(ignore_subscribe_messages=True, timeout=60.0)
if message:
log.info("Message received")
# Process message if received
if message['type'] == 'message':
payload = message['data']
if development_mode:
log.info(payload)
decoded_payload = base64.b64decode(payload)
data = json.loads(decoded_payload)
if "headers" in data:
if "subject" in data["headers"]:
subject = data["headers"]["subject"]
log.info(f"Subject: {subject}")
if "III Grading Required" in subject:
log.info("Subject found - let's go snatching!")
snatch_grading_work()
else:
log.info("Ignoring this email")
except Exception as e:
log.error(f"Error processing message: {e}")
sys.exit(1)
except KeyboardInterrupt:
log.info("Shutting down")
sys.exit(0)
except redis.RedisError as e:
log.error(f"Redis connection error: {e}")
sys.exit(1)
except Exception as e:
log.error(f"Unexpected error: {e}")
sys.exit(1)
if __name__ == "__main__":
logging.basicConfig(level=logging.INFO, stream=sys.stdout)
main()
import base64
import json
email_message = 'ewogICJoZWFkZXJzIjogewogICAgInJldHVybl9wYXRoIjogImZyZWRyaWsud2VuZHRAcHJvYWdpbGUuc2UiLAogICAgInJlY2VpdmVkIjogWwogICAgICAiYnkgbWFpbC13cjEtZjQxLmdvb2dsZS5jb20gd2l0aCBTTVRQIGlkIGZmYWNkMGI4NWE5N2QtM2E1MDdlODhiMGFzbzExNDk0NzVmOGYuMSAgICAgICAgZm9yIDxiNjI0Mzc5NzUxYjA3OGFkODkxMkBjbG91ZG1haWxpbi5uZXQ+OyBUaHUsIDI2IEp1biAyMDI1IDE0OjU5OjM2IC0wNzAwIiwKICAgICAgImZyb20gbG9jYWxob3N0ICgwLjkyLjIzMS4zNS5iYy5nb29nbGV1c2VyY29udGVudC5jb20uIFszNS4yMzEuOTIuMF0pICAgICAgICBieSBzbXRwLmdtYWlsLmNvbSB3aXRoIFVURjhTTVRQU0EgaWQgYTFlMGNjMWEyNTE0Yy04ODRkMWQ4N2RiMnNtMzkyMjI1MjQxLjE4LjIwMjUuMDYuMjYuMTQuNTkuMzUgICAgICAgIGZvciA8YjYyNDM3OTc1MWIwNzhhZDg5MTJAY2xvdWRtYWlsaW4ubmV0PiAgICAgICAgKHZlcnNpb249VExTMV8zIGNpcGhlcj1UTFNfQUVTXzEyOF9HQ01fU0hBMjU2IGJpdHM9MTI4LzEyOCk7IFRodSwgMjYgSnVuIDIwMjUgMTQ6NTk6MzUgLTA3MDAiCiAgICBdLAogICAgImRhdGUiOiAiVGh1LCAyNiBKdW4gMjAyNSAyMTo1OTozMyArMDAwMCIsCiAgICAiZnJvbSI6ICJGcmVkcmlrIFdlbmR0IDxmcmVkcmlrLndlbmR0QHByb2FnaWxlLnNlPiIsCiAgICAidG8iOiAiYjYyNDM3OTc1MWIwNzhhZDg5MTJAY2xvdWRtYWlsaW4ubmV0IiwKICAgICJtZXNzYWdlX2lkIjogIjxtY2R4ZTFndy4zNTdjNmE0NC1lNTExLTQwMTItODNlZS1iM2IyMGUzYTRjZjlAd2UuYXJlLnN1cGVyaHVtYW4uY29tPiIsCiAgICAic3ViamVjdCI6ICJUZXN0IDEiLAogICAgIm1pbWVfdmVyc2lvbiI6ICIxLjAiLAogICAgImNvbnRlbnRfdHlwZSI6ICJtdWx0aXBhcnQvYWx0ZXJuYXRpdmU7IGJvdW5kYXJ5PWQ5Y2I2MTcyYTMyY2U1NjllNTAyZThkNGMyY2RiYzI1YzExZDg4ZjBhNDZmZDk1ZWU5ZTRkY2Q1MTBlMyIsCiAgICAiZGtpbV9zaWduYXR1cmUiOiAidj0xOyBhPXJzYS1zaGEyNTY7IGM9cmVsYXhlZC9yZWxheGVkOyAgICAgICAgZD1wcm9hZ2lsZS5zZTsgcz1nb29nbGU7IHQ9MTc1MDk3NTE3NjsgeD0xNzUxNTc5OTc2OyBkYXJuPWNsb3VkbWFpbGluLm5ldDsgICAgICAgIGg9c3ViamVjdDpmcm9tOnRvOm1lc3NhZ2UtaWQ6ZGF0ZTptaW1lLXZlcnNpb246ZnJvbTp0bzpjYzpzdWJqZWN0ICAgICAgICAgOmRhdGU6bWVzc2FnZS1pZDpyZXBseS10bzsgICAgICAgIGJoPTZ2VGxTYnUrTFZlY2t3SlpoVVBTVkZXYVJsd0QrY2FZYjNteHNuK0gzZ3c9OyAgICAgICAgYj1UQ3NUb2EyMk4vbDFCVlMvdnJPNWlKOWZLZk96UFNwYUtacTlsVHJ3RFFwdllNRlhmT2JCYTRJbk0rTnd2ZVhVUG4gICAgICAgICBZeVJyRU15VCs1dW1EbERQbHRvanlzOXVaaG5telNtWXQ4ZHZudmhQbmVPbFJwTkJaWEtmSXYrV0lPMHZVWS9pa2pjTSAgICAgICAgIDV2M3pRc0NTSGFjUkVCVDlSajZ0emwwbWwzdVc3MU84aWZnamc9IiwKICAgICJ4X2dvb2dsZV9ka2ltX3NpZ25hdHVyZSI6ICJ2PTE7IGE9cnNhLXNoYTI1NjsgYz1yZWxheGVkL3JlbGF4ZWQ7ICAgICAgICBkPTFlMTAwLm5ldDsgcz0yMDIzMDYwMTsgdD0xNzUwOTc1MTc2OyB4PTE3NTE1Nzk5NzY7ICAgICAgICBoPXN1YmplY3Q6ZnJvbTp0bzptZXNzYWdlLWlkOmRhdGU6bWltZS12ZXJzaW9uOngtZ20tbWVzc2FnZS1zdGF0ZSAgICAgICAgIDpmcm9tOnRvOmNjOnN1YmplY3Q6ZGF0ZTptZXNzYWdlLWlkOnJlcGx5LXRvOyAgICAgICAgYmg9NnZUbFNidStMVmVja3dKWmhVUFNWRldhUmx3RCtjYVliM214c24rSDNndz07ICAgICAgICBiPXNDdXBCbWNJQy9ZQUpTamRpcTd6M1ByNVp6bnVGaFlkRTJxaGtZNkNDdmx5dW1oaG5tZDlhMEhKT0xSVStabUVGTCAgICAgICAgIDYvSndibzJCd3AwMllVZ1k1a2k3WlI2cGlZa29WK2FseTNNS0EveW5GcytMb2tFMWF1Ti9aRHBncDhZSU5hVnlRQklRICAgICAgICAgVXE1aHRnSStMNzhaeDVldjJ2RXpmMEpaTS94Z3pWdTlmMVhoMXRQMUl6bVpGemZtZzNQazlnM29OeG56NnBqSmRUTkYgICAgICAgICBibnYyTFNOcUZDMDZib0x2THpQZVhpbnVqTStma0Y3N3lST0N6T2NOSkd3bjBFYUt0UndiUldSU05pOVQ5RGFWVmxweCAgICAgICAgIExGN1VhdGJQTzFHNVBKTTl1bHBUZm9KdGRFeWU3ZFVWWHhWaExzZTFEeVhCcHBBZ0JZUFJDWEVHclRTSE0xbG1RK2tvICAgICAgICAgUDduQT09IiwKICAgICJ4X2dtX21lc3NhZ2Vfc3RhdGUiOiAiQU9KdTBZektJZG9KNlcxOTdTUGdjaWdPWkcxd1ZBY1cyUUQ4dVl4YWVRb1J2cW41QnhpZU9NNHVcdHpOS0FpQU50bXpwcWdwU0ZqR1NqTEhyc0Jud1NGeGg5a2NMclBRaTNKRmU4QWRuMXc2UEFpU2NFN3VuRG5TclJ3L2pMZmxiZ3NxeVx0blFtQU4iLAogICAgInhfZ21fZ2ciOiAiQVNiR25jdmI5SXFzeFluekxYYTFmK1Q4cjNmaFFBZUlRMS9TT3ZvdThMMk5QM1pwQ2pzaHV1RlNqejZYcThRcG5EQ1x0ZGczdERDcUxIdWZSL2dXUzFZY1JORFdHV1A1QU9BUSs3R0VxUTVaK2owM3dZa3pSUVdhay9rUzVHd05KdnhjYVRUalBrYmhoTlRyXHRXM04rRmltQVdjZGNZMXowVEdqMDFsWVNKWS9VRzdUbmxOeWlOZExRWkxIRnFLbjZ6S01udm1DOTY0THhWNWtrejJ5SXFaL202NGVcdEVmdktzM04xTEJVNG5Bb3NobUlDSmx4TGgwWk9WS3lnV2hZZmw0QWZ3N3NEaUFRWnZaZ3pyZVYwRXhzaHhRMks5a1Q3QlV5ZkQ5K1x0UEVMZjU0ZDFXdVFQaUNTMTV2bENrL2d5NExTdFRNYWJ2aFJZMzJFQk1JSG05cmhaaDRnMTFPRmtpdU8wbGdrOVFUUXFBVFJ5VWtOXHRYc3ZaZHhuRnZVNVI0WG1wVjdkY2hSNDhJVjJWYVBxd2ZLQmh3IiwKICAgICJ4X2dvb2dsZV9zbXRwX3NvdXJjZSI6ICJBR0hUK0lIWnRNemtxeHNtS1AzeFJkcUdIc29PS25sSWwvczRsY2hXbitiSStKcEdUZTBYeXhZWEdFQnhoSG9seGFKUzNVYmRFRzIzUlE9PSIsCiAgICAieF9yZWNlaXZlZCI6ICJieSAyMDAyOmFkZjpiMTliOjA6YjA6M2EzOjZlODU6YTUyOSB3aXRoIFNNVFAgaWQgZmZhY2QwYjg1YTk3ZC0zYThmZmNjOWVhNW1yNjc2NDIzZjhmLjUxLjE3NTA5NzUxNzU1NTE7ICAgICAgICBUaHUsIDI2IEp1biAyMDI1IDE0OjU5OjM1IC0wNzAwIChQRFQpIiwKICAgICJ4X21haWxlciI6ICJTdXBlcmh1bWFuIFdlYiAoMjAyNS0wNi0yNFQxOTowOTo1NC40MzJaKSIsCiAgICAieF9zdXBlcmh1bWFuX2lkIjogIm1jZHhlYjN5LmMzN2VkM2I4LThmZjMtNDNmZS1hMzBlLTU1NDFiZjdlZGFjNyIsCiAgICAieF9zdXBlcmh1bWFuX3RocmVhZF9pZCI6ICJkcmFmdDAwY2E3ZTc2ZjViZTNjMWIiLAogICAgInhfc3VwZXJodW1hbl9kcmFmdF9pZCI6ICJkcmFmdDAwMjU3OWVhY2RkNjViMGEiLAogICAgInhfZW50aXR5X3JlZl9pZCI6ICJtY2R4ZWIzeS5jMzdlZDNiOC04ZmYzLTQzZmUtYTMwZS01NTQxYmY3ZWRhYzciCiAgfSwKICAiZW52ZWxvcGUiOiB7CiAgICAidG8iOiAiYjYyNDM3OTc1MWIwNzhhZDg5MTJAY2xvdWRtYWlsaW4ubmV0IiwKICAgICJyZWNpcGllbnRzIjogWwogICAgICAiYjYyNDM3OTc1MWIwNzhhZDg5MTJAY2xvdWRtYWlsaW4ubmV0IgogICAgXSwKICAgICJmcm9tIjogImZyZWRyaWsud2VuZHRAcHJvYWdpbGUuc2UiLAogICAgImhlbG9fZG9tYWluIjogIm1haWwtd3IxLWY0MS5nb29nbGUuY29tIiwKICAgICJyZW1vdGVfaXAiOiAiMjA5Ljg1LjIyMS40MSIsCiAgICAidGxzIjogdHJ1ZSwKICAgICJ0bHNfY2lwaGVyIjogIlRMU3YxLjMiLAogICAgIm1kNSI6ICIxOGRmNjE5YjQzN2E5NmE0OTZkNTk2MWMzNmNiZWMxOCIsCiAgICAic3BmIjogewogICAgICAicmVzdWx0IjogInBhc3MiLAogICAgICAiZG9tYWluIjogInByb2FnaWxlLnNlIgogICAgfQogIH0sCiAgInBsYWluIjogIkVtYWlsIDFcclxuXHJcbipGcmVkcmlrIFdlbmR0KlxyXG5Qcm9kdWN0IExlYWRlcnNoaXAgQ29hY2hcclxuMDcwMiA3Nzg1MTEgKCB0ZWw6KzQ2NzAyNzc4NTExIClcclxuXHJcbipOw6RzdGEga3Vyc3RpbGxmw6RsbGVuKlxyXG5cclxuKiBQcm9mZXNzaW9uYWwgU2NydW0gUHJvZHVjdCBPd25lciAoIGh0dHBzOi8vcHJvYWdpbGUuc2UvUFNQTz91dG1fc291cmNlPWVtYWlsX3NpZ25hdHVyZSZ1dG1fbWVkaXVtPWVtYWlsJnV0bV9jYW1wYWlnbj1lbWFpbF9zaWduYXR1cmUgKVxyXG4yMC0yMSBhdWd1c3RpLCBHw7Z0ZWJvcmdcclxuKiBQcm9mZXNzaW9uYWwgQWdpbGUgQ29hY2ggKCBodHRwczovL3Byb2FnaWxlLnNlL1BBQz91dG1fc291cmNlPWVtYWlsX3NpZ25hdHVyZSZ1dG1fbWVkaXVtPWVtYWlsJnV0bV9jYW1wYWlnbj1lbWFpbF9zaWduYXR1cmUgKVxyXG4yNi0yNyBhdWd1c3RpLCBTdG9ja2hvbG1cclxuKiBQcm9mZXNzaW9uYWwgU2NydW0gTWFzdGVyICggaHR0cHM6Ly9wcm9hZ2lsZS5zZS9QU00/dXRtX3NvdXJjZT1lbWFpbF9zaWduYXR1cmUmdXRtX21lZGl1bT1lbWFpbCZ1dG1fY2FtcGFpZ249ZW1haWxfc2lnbmF0dXJlIClcclxuMjgtMjkgYXVndXN0aSwgR8O2dGVib3JnXHJcbiogUHJvZmVzc2lvbmFsIFNjcnVtIFByb2R1Y3QgT3duZXIgKCBodHRwczovL3Byb2FnaWxlLnNlL1BTUE8/dXRtX3NvdXJjZT1lbWFpbF9zaWduYXR1cmUmdXRtX21lZGl1bT1lbWFpbCZ1dG1fY2FtcGFpZ249ZW1haWxfc2lnbmF0dXJlIClcclxuMS0yIHNlcHRlbWJlciwgU3RvY2tob2xtXHJcbiogQWdpbGUgUHJhY3RpdGlvbmVyICggaHR0cHM6Ly9wcm9hZ2lsZS5zZS9BR0Y/dXRtX3NvdXJjZT1lbWFpbF9zaWduYXR1cmUmdXRtX21lZGl1bT1lbWFpbCZ1dG1fY2FtcGFpZ249ZW1haWxfc2lnbmF0dXJlIClcclxuMi0zIHNlcHRlbWJlciwgT25saW5lXHJcblxyXG4qTMOkc25pbmcgZnLDpW4gYmxvZ2dlbipcclxuXHJcbiogVGFsYW5nICsgdGVrbmlrID0gZnJhbWfDpW5nISBTw6Ugb21mYW1uYXIgdmkgQUkgKCBodHRwczovL3Byb2FnaWxlLnNlL2Jsb2cvdGFsYW5nLXRla25pay1mcmFtZ2FuZy1zYS1vbWZhbW5hci12aS1haSZ1dG1fc291cmNlPWVtYWlsX3NpZ25hdHVyZSZ1dG1fbWVkaXVtPWVtYWlsIClcclxuKiBGZW0gZsO2cmRlbGFyIG1lZCDigJ10w6RuayB0ZXN0IGbDtnJzdOKAnSAoIGh0dHBzOi8vcHJvYWdpbGUuc2UvYmxvZy9mZW0tZm9yZGVsYXItbWVkLXRhbmstdGVzdC1mb3JzdCZ1dG1fc291cmNlPWVtYWlsX3NpZ25hdHVyZSZ1dG1fbWVkaXVtPWVtYWlsIClcclxuKiBSZW5zYSBpIGtvZHNrb2dlbjogSW5zcGlyYXRpb24gZnLDpW4gbWluaW1hbGlzbSBvY2gga29kbmluZyAoIGh0dHBzOi8vcHJvYWdpbGUuc2UvYmxvZy9yZW5zYS1pLWtvZHNrb2dlbi1pbnNwaXJhdGlvbi1mcmFuLW1pbmltYWxpc20tb2NoLWtvZG5pbmcmdXRtX3NvdXJjZT1lbWFpbF9zaWduYXR1cmUmdXRtX21lZGl1bT1lbWFpbCApXHJcbiogV2hhdCBjYW4gd2UgbGVhcm4gZnJvbSBvdXIga2lkcz8gKCBodHRwczovL3Byb2FnaWxlLnNlL2Jsb2cvd2hhdC1jYW4td2UtbGVhcm4tZnJvbS1vdXIta2lkcyZ1dG1fc291cmNlPWVtYWlsX3NpZ25hdHVyZSZ1dG1fbWVkaXVtPWVtYWlsIClcclxuKiAyMCBRdWVzdGlvbnMgVG8gRWxpY2l0IFZhbHVlICggaHR0cHM6Ly9wcm9hZ2lsZS5zZS9ibG9nLzIwLXF1ZXN0aW9ucy10by1lbGljaXQtdmFsdWUmdXRtX3NvdXJjZT1lbWFpbF9zaWduYXR1cmUmdXRtX21lZGl1bT1lbWFpbCApIiwKICAiaHRtbCI6ICI8aHRtbD48aGVhZD48L2hlYWQ+PGJvZHk+PGRpdj48ZGl2PjxkaXYgY2xhc3M9XCJcIj5FbWFpbCAxPC9kaXY+PC9kaXY+PGRpdj48ZGl2IHN0eWxlPVwiZGlzcGxheTogbm9uZTsgYm9yZGVyOiAwcHg7IHdpZHRoOiAwcHg7IGhlaWdodDogMHB4OyBvdmVyZmxvdzogaGlkZGVuOyB2aXNpYmlsaXR5OiBoaWRkZW47XCI+PGltZyBzcmM9XCJodHRwczovL3Iuc3VwZXJodW1hbi5jb20vMHhKNEpZRU55cUpTMi01bF9uT29kaEtOaGN0bzg0aUtjeVlpQ3U4LW9RSk0zdmtJbXo0WFBOVHdLal95Z3NUOHhscHZlS25wa0ZhTUlDYmF2LWl5SFJMZER3NTBnRlVKQ3h4U2x1dGxwclE2Z3o0czBPcjBwdHIxYUwxV1k2RUpELTI1NkdoWmNUMVdHWEFnYzNQQW5GWkRFUUxGMW1HNEQ1aE9oMGFjeTJCOUtvVldwQWROSVF2VlhIZVc4UC1WLUhJdXZqVE5nTW8uZ2lmXCIgYWx0PVwiIFwiIHdpZHRoPVwiMVwiIGhlaWdodD1cIjBcIiBzdHlsZT1cImRpc3BsYXk6IG5vbmU7IGJvcmRlcjogMHB4OyB3aWR0aDogMHB4OyBoZWlnaHQ6IDBweDsgb3ZlcmZsb3c6IGhpZGRlbjsgdmlzaWJpbGl0eTogaGlkZGVuO1wiLz48IS0tICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAtLT48L2Rpdj48YnIvPjxkaXYgY2xhc3M9XCJnbWFpbF9zaWduYXR1cmVcIj48ZGl2Pjx0YWJsZSBjZWxsc3BhY2luZz1cIjBcIiBjZWxscGFkZGluZz1cIjBcIiBib3JkZXI9XCIwXCIgd2lkdGg9XCI2NDBcIj4gPHRib2R5Pjx0cj5cclxuICA8dGQgd2lkdGg9XCIxMDBcIj48aW1nIHN0eWxlPVwiYm9yZGVyLXJhZGl1czo1MCVcIiB3aWR0aD1cIjEwMFwiIHNyYz1cImh0dHBzOi8vczMuZXUtY2VudHJhbC0xLmFtYXpvbmF3cy5jb20vc3RhdGljLnByb2FnaWxlLnNlL3Blb3BsZS9zbWFsbC9mcmVkcmlrLXdlbmR0LmpwZ1wiLz48L3RkPlxyXG4gIDx0ZD7CoDxiPkZyZWRyaWsgV2VuZHQ8L2I+PGJyLz5cclxuICDCoFByb2R1Y3QgTGVhZGVyc2hpcCBDb2FjaDxici8+XHJcbiAgwqA8YSBocmVmPVwidGVsOis0NjcwMjc3ODUxMVwiIHRhcmdldD1cIl9ibGFua1wiIHJlbD1cIm5vb3BlbmVyIG5vcmVmZXJyZXJcIj4wNzAyIDc3ODUxMTwvYT48YnIvPlxyXG4gIDxpbWcgaGVpZ2h0PVwiMjBcIiBzcmM9XCJodHRwczovL3Byb2FnaWxlLnNlL2Fzc2V0cy9sb2dvLnBuZ1wiLz5cclxuICA8L3RkPlxyXG48L3RyPiA8L3Rib2R5PjwvdGFibGU+XHJcblxyXG48dGFibGUgY2VsbHBhZGRpbmc9XCIwXCIgY2VsbHNwYWNpbmc9XCIwXCIgYm9yZGVyPVwiMFwiIHdpZHRoPVwiNjQwXCI+IDx0Ym9keT48dHI+PHRkPlxyXG4gIDx0YWJsZSBhbGlnbj1cImxlZnRcIiBjZWxscGFkZGluZz1cIjIwXCIgY2VsbHNwYWNpbmc9XCIwXCIgYm9yZGVyPVwiMFwiIHdpZHRoPVwiMzIwXCI+PHRib2R5Pjx0cj48dGQ+XHJcbiAgPGRpdj48Yj5Ow6RzdGEga3Vyc3RpbGxmw6RsbGVuPC9iPjwvZGl2PlxyXG4gIDx1bD5cclxuPGxpPjxhIGhyZWY9XCJodHRwczovL3Byb2FnaWxlLnNlL1BTUE8/dXRtX3NvdXJjZT1lbWFpbF9zaWduYXR1cmUmYW1wO3V0bV9tZWRpdW09ZW1haWwmYW1wO3V0bV9jYW1wYWlnbj1lbWFpbF9zaWduYXR1cmVcIiB0YXJnZXQ9XCJfYmxhbmtcIiByZWw9XCJub29wZW5lciBub3JlZmVycmVyXCI+UHJvZmVzc2lvbmFsIFNjcnVtIFByb2R1Y3QgT3duZXI8L2E+PGJyLz4yMC0yMSBhdWd1c3RpLCBHw7Z0ZWJvcmc8L2xpPlxyXG48bGk+PGEgaHJlZj1cImh0dHBzOi8vcHJvYWdpbGUuc2UvUEFDP3V0bV9zb3VyY2U9ZW1haWxfc2lnbmF0dXJlJmFtcDt1dG1fbWVkaXVtPWVtYWlsJmFtcDt1dG1fY2FtcGFpZ249ZW1haWxfc2lnbmF0dXJlXCIgdGFyZ2V0PVwiX2JsYW5rXCIgcmVsPVwibm9vcGVuZXIgbm9yZWZlcnJlclwiPlByb2Zlc3Npb25hbCBBZ2lsZSBDb2FjaDwvYT48YnIvPjI2LTI3IGF1Z3VzdGksIFN0b2NraG9sbTwvbGk+XHJcbjxsaT48YSBocmVmPVwiaHR0cHM6Ly9wcm9hZ2lsZS5zZS9QU00/dXRtX3NvdXJjZT1lbWFpbF9zaWduYXR1cmUmYW1wO3V0bV9tZWRpdW09ZW1haWwmYW1wO3V0bV9jYW1wYWlnbj1lbWFpbF9zaWduYXR1cmVcIiB0YXJnZXQ9XCJfYmxhbmtcIiByZWw9XCJub29wZW5lciBub3JlZmVycmVyXCI+UHJvZmVzc2lvbmFsIFNjcnVtIE1hc3RlcjwvYT48YnIvPjI4LTI5IGF1Z3VzdGksIEfDtnRlYm9yZzwvbGk+XHJcbjxsaT48YSBocmVmPVwiaHR0cHM6Ly9wcm9hZ2lsZS5zZS9QU1BPP3V0bV9zb3VyY2U9ZW1haWxfc2lnbmF0dXJlJmFtcDt1dG1fbWVkaXVtPWVtYWlsJmFtcDt1dG1fY2FtcGFpZ249ZW1haWxfc2lnbmF0dXJlXCIgdGFyZ2V0PVwiX2JsYW5rXCIgcmVsPVwibm9vcGVuZXIgbm9yZWZlcnJlclwiPlByb2Zlc3Npb25hbCBTY3J1bSBQcm9kdWN0IE93bmVyPC9hPjxici8+MS0yIHNlcHRlbWJlciwgU3RvY2tob2xtPC9saT5cclxuPGxpPjxhIGhyZWY9XCJodHRwczovL3Byb2FnaWxlLnNlL0FHRj91dG1fc291cmNlPWVtYWlsX3NpZ25hdHVyZSZhbXA7dXRtX21lZGl1bT1lbWFpbCZhbXA7dXRtX2NhbXBhaWduPWVtYWlsX3NpZ25hdHVyZVwiIHRhcmdldD1cIl9ibGFua1wiIHJlbD1cIm5vb3BlbmVyIG5vcmVmZXJyZXJcIj5BZ2lsZSBQcmFjdGl0aW9uZXI8L2E+PGJyLz4yLTMgc2VwdGVtYmVyLCBPbmxpbmU8L2xpPlxyXG4gIDwvdWw+XHJcbiAgPC90ZD48L3RyPjwvdGJvZHk+PC90YWJsZT5cclxuXHJcbiAgPHRhYmxlIGFsaWduPVwicmlnaHRcIiBjZWxscGFkZGluZz1cIjIwXCIgY2VsbHNwYWNpbmc9XCIwXCIgYm9yZGVyPVwiMFwiIHdpZHRoPVwiMzIwXCI+XHJcbiAgPHRib2R5Pjx0cj48dGQ+XHJcbiAgPGRpdj48Yj5Mw6RzbmluZyBmcsOlbiBibG9nZ2VuPC9iPjwvZGl2PlxyXG4gIDx1bD5cclxuPGxpPjxhIGhyZWY9XCJodHRwczovL3Byb2FnaWxlLnNlL2Jsb2cvdGFsYW5nLXRla25pay1mcmFtZ2FuZy1zYS1vbWZhbW5hci12aS1haSZhbXA7dXRtX3NvdXJjZT1lbWFpbF9zaWduYXR1cmUmYW1wO3V0bV9tZWRpdW09ZW1haWxcIiB0YXJnZXQ9XCJfYmxhbmtcIiByZWw9XCJub29wZW5lciBub3JlZmVycmVyXCI+VGFsYW5nICsgdGVrbmlrID0gZnJhbWfDpW5nISBTw6Ugb21mYW1uYXIgdmkgQUk8L2E+PC9saT5cclxuPGxpPjxhIGhyZWY9XCJodHRwczovL3Byb2FnaWxlLnNlL2Jsb2cvZmVtLWZvcmRlbGFyLW1lZC10YW5rLXRlc3QtZm9yc3QmYW1wO3V0bV9zb3VyY2U9ZW1haWxfc2lnbmF0dXJlJmFtcDt1dG1fbWVkaXVtPWVtYWlsXCIgdGFyZ2V0PVwiX2JsYW5rXCIgcmVsPVwibm9vcGVuZXIgbm9yZWZlcnJlclwiPkZlbSBmw7ZyZGVsYXIgbWVkIOKAnXTDpG5rIHRlc3QgZsO2cnN04oCdPC9hPjwvbGk+XHJcbjxsaT48YSBocmVmPVwiaHR0cHM6Ly9wcm9hZ2lsZS5zZS9ibG9nL3JlbnNhLWkta29kc2tvZ2VuLWluc3BpcmF0aW9uLWZyYW4tbWluaW1hbGlzbS1vY2gta29kbmluZyZhbXA7dXRtX3NvdXJjZT1lbWFpbF9zaWduYXR1cmUmYW1wO3V0bV9tZWRpdW09ZW1haWxcIiB0YXJnZXQ9XCJfYmxhbmtcIiByZWw9XCJub29wZW5lciBub3JlZmVycmVyXCI+UmVuc2EgaSBrb2Rza29nZW46IEluc3BpcmF0aW9uIGZyw6VuIG1pbmltYWxpc20gb2NoIGtvZG5pbmc8L2E+PC9saT5cclxuPGxpPjxhIGhyZWY9XCJodHRwczovL3Byb2FnaWxlLnNlL2Jsb2cvd2hhdC1jYW4td2UtbGVhcm4tZnJvbS1vdXIta2lkcyZhbXA7dXRtX3NvdXJjZT1lbWFpbF9zaWduYXR1cmUmYW1wO3V0bV9tZWRpdW09ZW1haWxcIiB0YXJnZXQ9XCJfYmxhbmtcIiByZWw9XCJub29wZW5lciBub3JlZmVycmVyXCI+V2hhdCBjYW4gd2UgbGVhcm4gZnJvbSBvdXIga2lkcz88L2E+PC9saT5cclxuPGxpPjxhIGhyZWY9XCJodHRwczovL3Byb2FnaWxlLnNlL2Jsb2cvMjAtcXVlc3Rpb25zLXRvLWVsaWNpdC12YWx1ZSZhbXA7dXRtX3NvdXJjZT1lbWFpbF9zaWduYXR1cmUmYW1wO3V0bV9tZWRpdW09ZW1haWxcIiB0YXJnZXQ9XCJfYmxhbmtcIiByZWw9XCJub29wZW5lciBub3JlZmVycmVyXCI+MjAgUXVlc3Rpb25zIFRvIEVsaWNpdCBWYWx1ZTwvYT48L2xpPlxyXG4gIDwvdWw+XHJcbiAgPC90ZD48L3RyPjwvdGJvZHk+PC90YWJsZT5cclxuPC90ZD48L3RyPiA8L3Rib2R5PjwvdGFibGU+XHJcbjwvZGl2Pjxici8+PC9kaXY+PC9kaXY+PC9kaXY+PC9ib2R5PjwvaHRtbD4iLAogICJyZXBseV9wbGFpbiI6IG51bGwsCiAgImF0dGFjaG1lbnRzIjogWwoKICBdCn0='
email_message = 'ewogICJoZWFkZXJzIjogewogICAgInJlY2VpdmVkIjogImJ5IG1haWwtZWoxLWY1MS5nb29nbGUuY29tIHdpdGggU01UUCBpZCBhNjQwYzIzYTYyZjNhLWFlMDRkM2Q2M2U2c28yNjM5NDY2NjZiLjIgICAgICAgIGZvciA8YjYyNDM3OTc1MWIwNzhhZDg5MTJAY2xvdWRtYWlsaW4ubmV0PjsgVGh1LCAyNiBKdW4gMjAyNSAxNToxMjo0NSAtMDcwMCIsCiAgICAiZGF0ZSI6ICJGcmksIDI3IEp1biAyMDI1IDAwOjEyOjQ1ICswMjAwIiwKICAgICJmcm9tIjogIlByb0FnaWxlLXRlYW1ldCA8Zm9yd2FyZGluZy1ub3JlcGx5QGdvb2dsZS5jb20+IiwKICAgICJ0byI6ICJiNjI0Mzc5NzUxYjA3OGFkODkxMkBjbG91ZG1haWxpbi5uZXQiLAogICAgIm1lc3NhZ2VfaWQiOiAiPENBUGpIU0tEXzZnemFpcU1fSFh0UWhHZVJKSnRnSmJHYnJDSzlra0ZiPXAwNHZMeXY0QUBtYWlsLmdtYWlsLmNvbT4iLAogICAgInN1YmplY3QiOiAiKFByb0FnaWxlIEJla3LDpGZ0ZWxzZSBhdiB2aWRhcmViZWZvcmRyYW4g4oCTIHRhIGVtb3QgZS1wb3N0IGZyw6VuIGZyZWRyaWsud2VuZHRAcHJvYWdpbGUuc2UiLAogICAgIm1pbWVfdmVyc2lvbiI6ICIxLjAiLAogICAgImNvbnRlbnRfdHlwZSI6ICJ0ZXh0L3BsYWluOyBjaGFyc2V0PVVURi04IiwKICAgICJjb250ZW50X3RyYW5zZmVyX2VuY29kaW5nIjogInF1b3RlZC1wcmludGFibGUiLAogICAgImRraW1fc2lnbmF0dXJlIjogInY9MTsgYT1yc2Etc2hhMjU2OyBjPXJlbGF4ZWQvcmVsYXhlZDsgICAgICAgIGQ9Z29vZ2xlLmNvbTsgcz0yMDIzMDYwMTsgdD0xNzUwOTc1OTY1OyB4PTE3NTE1ODA3NjU7IGRhcm49Y2xvdWRtYWlsaW4ubmV0OyAgICAgICAgaD1jb250ZW50LXRyYW5zZmVyLWVuY29kaW5nOnRvOmZyb206c3ViamVjdDptZXNzYWdlLWlkOmRhdGUgICAgICAgICA6bWltZS12ZXJzaW9uOmZyb206dG86Y2M6c3ViamVjdDpkYXRlOm1lc3NhZ2UtaWQ6cmVwbHktdG87ICAgICAgICBiaD0xM3d0ZmJQY2RhWG42WVFpZFdpY0dITys0NTVmMkVOckpSSHl5WjBJOFVvPTsgICAgICAgIGI9YUltUGlNb00vYzVGRDBNSDA1M2QxcVBqWFhtMGxhamw5Nmx2UlhFSlNNb2tSVnEram9TZkVvUVFVS3VoamNGaWdzICAgICAgICAgSjF6aWw1dDlEQ3B0aGFlNnFVSU03dlZtbmc1a0pacExNa0JTcUZ5UEFNWjFoT2p0bmlmYVdUZDhDUjB4OGlVUU0xSWMgICAgICAgICBmL0hubGNrNzFadENMb0Vrc0dPOUNkNUE1NTc4dVV6MUJqbk5VNkljOGtNcjN5NHE4azBYdmsrU3grdFF6OVFRNFg3NSAgICAgICAgIHhuNVA1S3J2MkhZTkhLYjF3U2FaWkxrUDJNS09XZU0yUDhKbWtiK0NJY0l2RVBYaE1XbFNLMVdqNysybkZEL21vc3pjICAgICAgICAgcDU4cFVJTjNvK01qMHU1Y3RMUmdaakNkRWEvdDZpVHhXaVZXSVJPSTM1dlZETHA3WjFkQjlWYmJpYlJsWmxyWmJFbnIgICAgICAgICAzM0pnPT0iLAogICAgInhfZ29vZ2xlX2RraW1fc2lnbmF0dXJlIjogInY9MTsgYT1yc2Etc2hhMjU2OyBjPXJlbGF4ZWQvcmVsYXhlZDsgICAgICAgIGQ9MWUxMDAubmV0OyBzPTIwMjMwNjAxOyB0PTE3NTA5NzU5NjU7IHg9MTc1MTU4MDc2NTsgICAgICAgIGg9Y29udGVudC10cmFuc2Zlci1lbmNvZGluZzp0bzpmcm9tOnN1YmplY3Q6bWVzc2FnZS1pZDpkYXRlICAgICAgICAgOm1pbWUtdmVyc2lvbjp4LWdtLW1lc3NhZ2Utc3RhdGU6ZnJvbTp0bzpjYzpzdWJqZWN0OmRhdGU6bWVzc2FnZS1pZCAgICAgICAgIDpyZXBseS10bzsgICAgICAgIGJoPTEzd3RmYlBjZGFYbjZZUWlkV2ljR0hPKzQ1NWYyRU5ySlJIeXlaMEk4VW89OyAgICAgICAgYj13VFY5ZnAzaXVUaS9DaE9iNjlId2hxVzVzRStVVkNDTHFFSm1jYXRTZm13MVozMGsvNGJWR0VyWmIvbW1XNW5FYWIgICAgICAgICBWeDNFL3pGazJRR0E1K2MyWG8ya1RGRnpMR1c5bXhvQjYxK0V5UElYWFRYd2w4cUJ3akJDQkN1dG1ucnlmN1dYNE5pdyAgICAgICAgIHpxeXFUb2pVeFVxT2FxLzlJa3kvdTJqTWh1alQ4SW8wS0FhNTByYllVaWhRd1BJajJ4NFdHdWwzVHVlZ0UycjB1Tk9VICAgICAgICAgTGg0VzRMbWpCajl3RC94NE03U3ROanhRb05zY1BSbWZNcUp0dkVxZEVOSmFRSkxrS243WTZWSjVlMUtRTEE5K2oyTGMgICAgICAgICBHbDN5anRkUFJ5WHFRejdtRlh2TllMVXF4aEMzT1AvbVJaNFRZWlJwTjE0U3d1QzBJdmF0MWxMTjZNTVoxWXdDekJ1ZyAgICAgICAgIHpoZWc9PSIsCiAgICAieF9nbV9tZXNzYWdlX3N0YXRlIjogIkFPSnUwWXd1b1BiNUdaWVk2UHR2ODVMdFVTdk1GZ05zK1hoRXZpUHZJQ0RGY2w0Vm0yQnZlWUtzXHRNa0VGbWxhdEZIRjRKdzFEUlhmcmdYRGJnT1d6cENtUWRGNVltZ0tzS1ZGZFNSZXdibDFtemtwelIyM1VWVXMzRUFOdVluZ25MbXJcdHJacm1GMzRzOEZQek5NaG9sZGlVODdKMW1TUnNhZklvNTBpUTRMQzVaQ2ttUTk2WVFXVTlvUlRBTlQ4Mk54TmxhTDA0eCIsCiAgICAieF9nbV9nZyI6ICJBU2JHbmN2UVBLaytpVFptL0xTdFdvdlN6a0tuT1hlVUtTMHRmTjJzU3gySlJKTk1oVVZoTFlUc2U5cXMxMWdweWhOXHRvcnB6UzNVNTdvL2hTQjhpUmw1VG9jc3FpYW5rMUNEcGFjVWVEYnNCcW8yNU9rVTJWendjcXl5aTdQdFdVc21HOVJDZE9waFNxc1BcdHVxVkxncW9QTkFGL2VDRXNkOXgwM3dwK1lseG1ycVlOdjl0Y20vWlVNcCIsCiAgICAieF9nb29nbGVfc210cF9zb3VyY2UiOiAiQUdIVCtJRVhOSVplakpETnVwMmM1MkRIRG5tdzBIcjVSSkR5WmxycVpiZUxoNDZTK2NvNTVGRHJvNnpLUEtEZ3h2dFZGbmVTNmhsT2VZOGVadUdDblY5NVUwaE83VUJLZ3RPL3RnPT0iLAogICAgInhfcmVjZWl2ZWQiOiAiYnkgMjAwMjphMTc6OTA3OjcyMDc6YjA6YWQ4Ojg1Mjk6NGY3NyB3aXRoIFNNVFAgaWQgYTY0MGMyM2E2MmYzYS1hZTM1MDBiOWNjOG1yNzUxMDU3NjZiLjM4LjE3NTA5NzU5NjUxMDY7IFRodSwgMjYgSnVuIDIwMjUgMTU6MTI6NDUgLTA3MDAgKFBEVCkiLAogICAgInhfZ29vZ2xlX2FkZHJlc3NfY29uZmlybWF0aW9uIjogIjdtMzZpNmFlN0VwLVBLbjRKVFduT2dxM3dGcyIsCiAgICAieF9nbV9mZWF0dXJlcyI6ICJBYzEyRlh4WEJtUjVMeUhvbWIzZUl3SV9RaTZuOV9KOFZYLTNYckpzZFhvclZBY2NiOExfLUI5eHRpaTQ3elUiCiAgfSwKICAiZW52ZWxvcGUiOiB7CiAgICAidG8iOiAiYjYyNDM3OTc1MWIwNzhhZDg5MTJAY2xvdWRtYWlsaW4ubmV0IiwKICAgICJyZWNpcGllbnRzIjogWwogICAgICAiYjYyNDM3OTc1MWIwNzhhZDg5MTJAY2xvdWRtYWlsaW4ubmV0IgogICAgXSwKICAgICJmcm9tIjogImZvcndhcmRpbmctbm9yZXBseUBnb29nbGUuY29tIiwKICAgICJoZWxvX2RvbWFpbiI6ICJtYWlsLWVqMS1mNTEuZ29vZ2xlLmNvbSIsCiAgICAicmVtb3RlX2lwIjogIjIwOS44NS4yMTguNTEiLAogICAgInRscyI6IHRydWUsCiAgICAidGxzX2NpcGhlciI6ICJUTFN2MS4zIiwKICAgICJtZDUiOiAiZWE3MWM3NmY2MGNlYWM4MjI2NDhlMjdmNTNkZjhmZTkiLAogICAgInNwZiI6IHsKICAgICAgInJlc3VsdCI6ICJub25lIiwKICAgICAgImRvbWFpbiI6ICJnb29nbGUuY29tIgogICAgfQogIH0sCiAgInBsYWluIjogImZyZWRyaWsud2VuZHRAcHJvYWdpbGUuc2UgaGFyIGJlZ8OkcnQgYXR0IGF1dG9tYXRpc2t0IHZpZGFyZWJlZm9yZHJhXHJcbmUtcG9zdCB0aWxsIGRpbiBlLXBvc3RhZHJlc3MgYjYyNDM3OTc1MWIwNzhhZDg5MTJAY2xvdWRtYWlsaW4ubmV0LlxyXG5cclxuT20gZHUgdmlsbCB0aWxsw6V0YSBhdHQgZnJlZHJpay53ZW5kdEBwcm9hZ2lsZS5zZSBhdXRvbWF0aXNrdFxyXG52aWRhcmViZWZvcmRyYXIgZS1wb3N0IHRpbGwgZGluIGFkcmVzc1xyXG5rbGlja2FyIGR1IHDDpSBsw6Rua2VuIG5lZGFuIG9jaCBnb2Rrw6RubmVyIGJlZ8OkcmFuOlxyXG5cclxuaHR0cHM6Ly9tYWlsLXNldHRpbmdzLmdvb2dsZS5jb20vbWFpbC92Zi0lNUJBTkdqZEpfdXV6Slo4Y2tkVVFVQUNTUTBYWmZMekxVa05IZlNIbjNncGlTZFEyck02Qks3d0VwdDh2ZTlkTTJ0MF9ZRll2eWV4aFJyejgzYzBPdzFnekp0ZmotQ2tPVnlXakF4bEttdW1RJTVELTlrdWNValNUQVBEMkp0SHFySFpVZ3MwRmtVMFxyXG5cclxuT20gZHUga2xpY2thciBww6UgbMOkbmtlbiBvY2ggZGVuIHZlcmthciB2YXJhIHRyYXNpZyBrb3BpZXJhciBvY2hcclxua2xpc3RyYXIgZHUgaW4gZGVuIGkgZXR0XHJcbm55dHQgd2ViYmzDpHNhcmbDtm5zdGVyLlxyXG5cclxuVGFjayBmw7ZyIGF0dCBkdSBhbnbDpG5kZXIgUHJvQWdpbGUuXHJcblxyXG5Ww6RubGlnYSBow6Rsc25pbmdhcixcclxuXHJcblRlYW1ldCBiYWtvbSBQcm9BZ2lsZVxyXG5cclxuT20gZHUgaW50ZSB2aWxsIGdvZGvDpG5uYSBkZW4gaMOkciBiZWfDpHJhbiBiZWjDtnZlciBkdSBpbnRlIGfDtnJhIG7DpWdvdCBtZXIuXHJcbmZyZWRyaWsud2VuZHRAcHJvYWdpbGUuc2Uga2FuIGJhcmEgYXV0b21hdGlza3QgdmlkYXJlYmVmb3JkcmFcclxubWVkZGVsYW5kZW4gdGlsbCBkaW4gZS1wb3N0YWRyZXNzXHJcbm9tIGR1IGJla3LDpGZ0YXIgYmVnw6RyYW4gZ2Vub20gYXR0IGtsaWNrYSBww6UgbMOkbmtlbiBvdmFuLiBPbSBkdSBoYXJcclxucsOla2F0IGtsaWNrYXQgcMOlIGzDpG5rZW4gYXYgbWlzc3RhZ1xyXG5vY2ggZHUgdmlsbCBpbnRlIHRpbGzDpXRhIGF0dCBmcmVkcmlrLndlbmR0QHByb2FnaWxlLnNlIGF1dG9tYXRpc2t0XHJcbnZpZGFyZWJlZm9yZHJhciBtZWRkZWxhbmRlbiB0aWxsIGRpbiBhZHJlc3Mga2xpY2thciBkdSBww6UgZGVuIGjDpHIgbMOkbmtlblxyXG5mw7ZyIGF0dCBhdmJyeXRhIHZlcmlmaWVyaW5nZW46XHJcbmh0dHBzOi8vbWFpbC1zZXR0aW5ncy5nb29nbGUuY29tL21haWwvdWYtJTVCQU5HamRKOGZUeE9DVkZXcXhYSFd0aTFHVHpwUUdjY0E2bVZXbGt3c1VVXzdQWlU0bXJtamF0RzZibUVPRnFPLWhNRklBc21IdjRvTW1tUFpBcUdrVnFQMjMxMktKWGlmQlotd2RMYkM2ZyU1RC05a3VjVWpTVEFQRDJKdEhxckhaVWdzMEZrVTBcclxuXHJcbk9tIGR1IHZpbGwgdmV0YSBtZXIgb20gdmFyZsO2ciBkdSBoYXIgZsOldHQgZGV0IGjDpHIgbWVkZGVsYW5kZXQga2FuIGR1XHJcbmJlc8O2a2E6IGh0dHA6Ly9zdXBwb3J0Lmdvb2dsZS5jb20vbWFpbC9iaW4vYW5zd2VyLnB5P2Fuc3dlcj0xODQ5NzMuXHJcblxyXG5TdmFyYSBpbnRlIHDDpSBkZXQgaMOkciBtZWRkZWxhbmRldC4gT20gZHUgdmlsbCBrb250YWt0YVxyXG5Hb29nbGUtY29tLXRlYW1ldCBsb2dnYXIgZHUgaW4gcMOlIGRpdHQga29udG8gb2NoIGtsaWNrYXIgcMOlIEhqw6RscFxyXG5ow7Znc3QgdXBwIHDDpSB2YWxmcmkgc2lkYS4gS2xpY2thIHNlZGFuIHDDpSBLb250YWt0YSBvc3MgbMOkbmdzdCBuZWQgaVxyXG5oasOkbHBjZW50cmV0LlxyXG4iLAogICJodG1sIjogbnVsbCwKICAicmVwbHlfcGxhaW4iOiBudWxsLAogICJhdHRhY2htZW50cyI6IFsKCiAgXQp9'
email_message = 'ewogICJoZWFkZXJzIjogewogICAgInJlY2VpdmVkIjogImJ5IG1haWwtZWoxLWY1MS5nb29nbGUuY29tIHdpdGggU01UUCBpZCBhNjQwYzIzYTYyZjNhLWFlMGRkN2FjMWY1c28xNzAzNTAyNjZiLjIgICAgICAgIGZvciA8YjYyNDM3OTc1MWIwNzhhZDg5MTJAY2xvdWRtYWlsaW4ubmV0PjsgVGh1LCAyNiBKdW4gMjAyNSAxNToyMDowMCAtMDcwMCIsCiAgICAiZGF0ZSI6ICJGcmksIDI3IEp1biAyMDI1IDAwOjIwOjAwICswMjAwIiwKICAgICJmcm9tIjogIlByb0FnaWxlLXRlYW1ldCA8Zm9yd2FyZGluZy1ub3JlcGx5QGdvb2dsZS5jb20+IiwKICAgICJ0byI6ICJiNjI0Mzc5NzUxYjA3OGFkODkxMkBjbG91ZG1haWxpbi5uZXQiLAogICAgIm1lc3NhZ2VfaWQiOiAiPENBUGpIU0tEVm9PK1FhNVE1LVIyX0RmOHZSUzYzbVNXS0Y3QTg1MzVwM1VBaHRzRTBDZ0BtYWlsLmdtYWlsLmNvbT4iLAogICAgInN1YmplY3QiOiAiKFByb0FnaWxlIEJla3LDpGZ0ZWxzZSBhdiB2aWRhcmViZWZvcmRyYW4g4oCTIHRhIGVtb3QgZS1wb3N0IGZyw6VuIGZyZWRyaWsud2VuZHRAcHJvYWdpbGUuc2UiLAogICAgIm1pbWVfdmVyc2lvbiI6ICIxLjAiLAogICAgImNvbnRlbnRfdHlwZSI6ICJ0ZXh0L3BsYWluOyBjaGFyc2V0PVVURi04IiwKICAgICJjb250ZW50X3RyYW5zZmVyX2VuY29kaW5nIjogInF1b3RlZC1wcmludGFibGUiLAogICAgImRraW1fc2lnbmF0dXJlIjogInY9MTsgYT1yc2Etc2hhMjU2OyBjPXJlbGF4ZWQvcmVsYXhlZDsgICAgICAgIGQ9Z29vZ2xlLmNvbTsgcz0yMDIzMDYwMTsgdD0xNzUwOTc2NDAwOyB4PTE3NTE1ODEyMDA7IGRhcm49Y2xvdWRtYWlsaW4ubmV0OyAgICAgICAgaD1jb250ZW50LXRyYW5zZmVyLWVuY29kaW5nOnRvOmZyb206c3ViamVjdDptZXNzYWdlLWlkOmRhdGUgICAgICAgICA6bWltZS12ZXJzaW9uOmZyb206dG86Y2M6c3ViamVjdDpkYXRlOm1lc3NhZ2UtaWQ6cmVwbHktdG87ICAgICAgICBiaD1Rdjd6c0loR21vZEdNRThYZjBXQjhXNWZlVEx6RmRvcldnKzM5SXdaemg0PTsgICAgICAgIGI9b1c2a1UvcGMrZUtIUk9WL1cwNDQya2M3UllTNUhuZ1h0S2cwRzc1SjhuN3pObThJZG1GZm1JczQ1TkJ5OThFVmlsICAgICAgICAgMFVGR1UvbUFJa3lFanMzT2RQc2NKcFhFV1lYck1ZT3duUXRHTHpBVXpJUWNsOWFBTHA5bXJIUXh2OHVFVFZYYVBQRG8gICAgICAgICBzQTEvTUlrdXp4dFhmeXQ5YmdYSFgxOGRVTUdKTlQybzd3elY4MGxrUUlYbnArcGpwQjE4MXk4MmxFZk5ZSnB1Q3F0SiAgICAgICAgIHgrSXZzeTgwRmJpbFBvOFBiZkJxMFJvelJoK05Sam5IWkNjRXk5SzgzdmVQMnRyNnVnYjhKU0VaWndNYkdYTG5TWHVrICAgICAgICAgdDVFYW1JVnhNc08rZ01NS2FOZ3RRY09QQWx4YTVob0ZZVDJBc2VNMlZIVmgxVUpWWGJqWVV6SFUwQTI0NEJxVmtHRFYgICAgICAgICBUNVh3PT0iLAogICAgInhfZ29vZ2xlX2RraW1fc2lnbmF0dXJlIjogInY9MTsgYT1yc2Etc2hhMjU2OyBjPXJlbGF4ZWQvcmVsYXhlZDsgICAgICAgIGQ9MWUxMDAubmV0OyBzPTIwMjMwNjAxOyB0PTE3NTA5NzY0MDA7IHg9MTc1MTU4MTIwMDsgICAgICAgIGg9Y29udGVudC10cmFuc2Zlci1lbmNvZGluZzp0bzpmcm9tOnN1YmplY3Q6bWVzc2FnZS1pZDpkYXRlICAgICAgICAgOm1pbWUtdmVyc2lvbjp4LWdtLW1lc3NhZ2Utc3RhdGU6ZnJvbTp0bzpjYzpzdWJqZWN0OmRhdGU6bWVzc2FnZS1pZCAgICAgICAgIDpyZXBseS10bzsgICAgICAgIGJoPVF2N3pzSWhHbW9kR01FOFhmMFdCOFc1ZmVUTHpGZG9yV2crMzlJd1p6aDQ9OyAgICAgICAgYj1jcEZOd0Nic2F3TjVxTE56NDNmU2VxVjhROXFwZnlTUWJUaUViK3dnYnErT3FPUmpJQ1VuTHJLN2NKYTNMdTlHVUogICAgICAgICBFV0xUSFE0dDhxNUZqVThmdjFpNHJlMExvUFZGRWh5amhCMlREQXFQVVY3YURyYXMvOFBSZ0tJN3dpblFHcW9mNGp4SCAgICAgICAgIFNXUTJUOHJZUXR4cHdVenhJMTlpR2VTZnZWaVA3RWcxQm9QclMwSWVOWlNZQkZSMzRDaG9oalppVUgwaGJWU3F5VzF0ICAgICAgICAgeVp3Mlo1MUpubFIzMlF1U0pBbFg1RFR3M2ExZmUreU1DajY4d0JDeFlLZGEzRDBIVm50QU9ic3hnL1p6YmkvRHFGSE0gICAgICAgICB6OUhFMXlNNGl6WTcxN2F3QnlhM0xvenJJbnlZVzVqNWFWQVFJRXV4RzRSYzdkdXFIR0tjeW5VRC96a05TVGZRL2JaeiAgICAgICAgIEp2ZkE9PSIsCiAgICAieF9nbV9tZXNzYWdlX3N0YXRlIjogIkFPSnUwWXhoNU4wbUoyYWxPNUpqTVl3SzhseFlpWlprNHZZVkIrT0NHcHFXdW9xUWlUY3ZoRXZ4XHRkVzJpSlplUmNJaEdKZW5QbHNyMFJONHUrRWV0RlZxVlZZWUdYeWwvd1NJTlhnQitIU1JscWUvV05TNjBuMzQ2LzVKR2g1dUw5VW9cdHVsWWxaNHEveDFVYmdCMjlaanVYanluem41L2RYNWUvdktLWGtoWTVpZi9PdmpuQWpGdHRYYmZGL1FDNGxEOVIrSlB4USIsCiAgICAieF9nbV9nZyI6ICJBU2JHbmN2V2NDanYrWEVqRGFMcEdUNVJiQVFhVEVjeE1keTFyeDZubzJYZ0V3YzZ2cWV4N1RlTDFaZ1FuMHBjTW1JXHRiZExETWhTb2hsSGZTdjNhMmZmVXByYStPM25wdGhJQjNlSWhNRGJiQnZ2dWkwMjVjZTVnczVvaUpHKzJtVTNUS0J2MVMvaWdkcEtcdEkvYkVDaE4xVkZ5RWtHak13WjVzTDNMZFBlcHJxOFp5cmpuZ3RCS2tndSIsCiAgICAieF9nb29nbGVfc210cF9zb3VyY2UiOiAiQUdIVCtJRXZOOVlyRXM3dk1ibVI4MjByUEZ0aUJUNUQ3bE1WZjByQjdtT2dUOE0xRDN6K2RYQ01SL3JtVUxUL0hpb085YVgrUjRHZ2d5cnErL0I3cHJGYjh1cWNMSmlNNG9sVk5BPT0iLAogICAgInhfcmVjZWl2ZWQiOiAiYnkgMjAwMjphMTc6OTA3OjYwMjM6YjA6YWUwOmM4YjI6M2ZjMCB3aXRoIFNNVFAgaWQgYTY0MGMyM2E2MmYzYS1hZTM0ZmQ0NmE3YW1yNDc4MzkzNjZiLjEwLjE3NTA5NzY0MDAyMjg7IFRodSwgMjYgSnVuIDIwMjUgMTU6MjA6MDAgLTA3MDAgKFBEVCkiLAogICAgInhfZ29vZ2xlX2FkZHJlc3NfY29uZmlybWF0aW9uIjogIjdtMzZpNmFlN0VwLVBLbjRKVFduT2dxM3dGcyIsCiAgICAieF9nbV9mZWF0dXJlcyI6ICJBYzEyRlh5ZmxNWDVvWGthdTdiX3dqU2oySGM4QW1heXcyMV96QUM4Q01iU0o5Slc4dnVBVExIMzdWU1ZrLXMiCiAgfSwKICAiZW52ZWxvcGUiOiB7CiAgICAidG8iOiAiYjYyNDM3OTc1MWIwNzhhZDg5MTJAY2xvdWRtYWlsaW4ubmV0IiwKICAgICJyZWNpcGllbnRzIjogWwogICAgICAiYjYyNDM3OTc1MWIwNzhhZDg5MTJAY2xvdWRtYWlsaW4ubmV0IgogICAgXSwKICAgICJmcm9tIjogImZvcndhcmRpbmctbm9yZXBseUBnb29nbGUuY29tIiwKICAgICJoZWxvX2RvbWFpbiI6ICJtYWlsLWVqMS1mNTEuZ29vZ2xlLmNvbSIsCiAgICAicmVtb3RlX2lwIjogIjIwOS44NS4yMTguNTEiLAogICAgInRscyI6IHRydWUsCiAgICAidGxzX2NpcGhlciI6ICJUTFN2MS4zIiwKICAgICJtZDUiOiAiNWRiZWFmZWFjYzdhZjU4OTY2YzY0OGNmZTI4YWMyZjYiLAogICAgInNwZiI6IHsKICAgICAgInJlc3VsdCI6ICJub25lIiwKICAgICAgImRvbWFpbiI6ICJnb29nbGUuY29tIgogICAgfQogIH0sCiAgInBsYWluIjogImZyZWRyaWsud2VuZHRAcHJvYWdpbGUuc2UgaGFyIGJlZ8OkcnQgYXR0IGF1dG9tYXRpc2t0IHZpZGFyZWJlZm9yZHJhXHJcbmUtcG9zdCB0aWxsIGRpbiBlLXBvc3RhZHJlc3MgYjYyNDM3OTc1MWIwNzhhZDg5MTJAY2xvdWRtYWlsaW4ubmV0LlxyXG5cclxuT20gZHUgdmlsbCB0aWxsw6V0YSBhdHQgZnJlZHJpay53ZW5kdEBwcm9hZ2lsZS5zZSBhdXRvbWF0aXNrdFxyXG52aWRhcmViZWZvcmRyYXIgZS1wb3N0IHRpbGwgZGluIGFkcmVzc1xyXG5rbGlja2FyIGR1IHDDpSBsw6Rua2VuIG5lZGFuIG9jaCBnb2Rrw6RubmVyIGJlZ8OkcmFuOlxyXG5cclxuaHR0cHM6Ly9tYWlsLmdvb2dsZS5jb20vbWFpbC92Zi0lNUJBTkdqZEpfblNBZXpFaE1WUDdicWROYW43My1wbWpJandzV1YydFNaRjBzVm82cjR6SHFOaFNta0VaY0tlRmVUWERIMEdKMm9WQmMzeDZzTnJxRmZTSF85dGc4UllFS0FMeWxxc3FsZjV3JTVELTlrdWNValNUQVBEMkp0SHFySFpVZ3MwRmtVMFxyXG5cclxuT20gZHUga2xpY2thciBww6UgbMOkbmtlbiBvY2ggZGVuIHZlcmthciB2YXJhIHRyYXNpZyBrb3BpZXJhciBvY2hcclxua2xpc3RyYXIgZHUgaW4gZGVuIGkgZXR0XHJcbm55dHQgd2ViYmzDpHNhcmbDtm5zdGVyLlxyXG5cclxuVGFjayBmw7ZyIGF0dCBkdSBhbnbDpG5kZXIgUHJvQWdpbGUuXHJcblxyXG5Ww6RubGlnYSBow6Rsc25pbmdhcixcclxuXHJcblRlYW1ldCBiYWtvbSBQcm9BZ2lsZVxyXG5cclxuT20gZHUgaW50ZSB2aWxsIGdvZGvDpG5uYSBkZW4gaMOkciBiZWfDpHJhbiBiZWjDtnZlciBkdSBpbnRlIGfDtnJhIG7DpWdvdCBtZXIuXHJcbmZyZWRyaWsud2VuZHRAcHJvYWdpbGUuc2Uga2FuIGJhcmEgYXV0b21hdGlza3QgdmlkYXJlYmVmb3JkcmFcclxubWVkZGVsYW5kZW4gdGlsbCBkaW4gZS1wb3N0YWRyZXNzXHJcbm9tIGR1IGJla3LDpGZ0YXIgYmVnw6RyYW4gZ2Vub20gYXR0IGtsaWNrYSBww6UgbMOkbmtlbiBvdmFuLiBPbSBkdSBoYXJcclxucsOla2F0IGtsaWNrYXQgcMOlIGzDpG5rZW4gYXYgbWlzc3RhZ1xyXG5vY2ggZHUgdmlsbCBpbnRlIHRpbGzDpXRhIGF0dCBmcmVkcmlrLndlbmR0QHByb2FnaWxlLnNlIGF1dG9tYXRpc2t0XHJcbnZpZGFyZWJlZm9yZHJhciBtZWRkZWxhbmRlbiB0aWxsIGRpbiBhZHJlc3Mga2xpY2thciBkdSBww6UgZGVuIGjDpHIgbMOkbmtlblxyXG5mw7ZyIGF0dCBhdmJyeXRhIHZlcmlmaWVyaW5nZW46XHJcbmh0dHBzOi8vbWFpbC5nb29nbGUuY29tL21haWwvdWYtJTVCQU5HamRKX1dlYW1ucEhfaDd4Zks0QTdVRVdfZThuazV1ZldlRzFFZWlHUzM0R3l1R2tHaF94dklYRXhWOS16QlRFR3U3VmJXeWVwNGlRS2ttaC11RVRwMUJPMThVSHczUGw1ZkNCUWtvdyU1RC05a3VjVWpTVEFQRDJKdEhxckhaVWdzMEZrVTBcclxuXHJcbk9tIGR1IHZpbGwgdmV0YSBtZXIgb20gdmFyZsO2ciBkdSBoYXIgZsOldHQgZGV0IGjDpHIgbWVkZGVsYW5kZXQga2FuIGR1XHJcbmJlc8O2a2E6IGh0dHA6Ly9zdXBwb3J0Lmdvb2dsZS5jb20vbWFpbC9iaW4vYW5zd2VyLnB5P2Fuc3dlcj0xODQ5NzMuXHJcblxyXG5TdmFyYSBpbnRlIHDDpSBkZXQgaMOkciBtZWRkZWxhbmRldC4gT20gZHUgdmlsbCBrb250YWt0YVxyXG5Hb29nbGUtY29tLXRlYW1ldCBsb2dnYXIgZHUgaW4gcMOlIGRpdHQga29udG8gb2NoIGtsaWNrYXIgcMOlIEhqw6RscFxyXG5ow7Znc3QgdXBwIHDDpSB2YWxmcmkgc2lkYS4gS2xpY2thIHNlZGFuIHDDpSBLb250YWt0YSBvc3MgbMOkbmdzdCBuZWQgaVxyXG5oasOkbHBjZW50cmV0LlxyXG4iLAogICJodG1sIjogbnVsbCwKICAicmVwbHlfcGxhaW4iOiBudWxsLAogICJhdHRhY2htZW50cyI6IFsKCiAgXQp9'
decoded = base64.b64decode(email_message)
data = json.loads(decoded)
print(data)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment