Skip to content

Instantly share code, notes, and snippets.

@developerck
Last active May 15, 2023 06:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save developerck/ab26e514b1831137131d93519879e58f to your computer and use it in GitHub Desktop.
Save developerck/ab26e514b1831137131d93519879e58f to your computer and use it in GitHub Desktop.
create jira ticket and add comment from email

lambda function for creating Jira ticket and comment through Email forwarding

## save messge id in dynamo db for making reply as comment
import boto3
import botocore
from botocore.exceptions import ClientError
from boto3.dynamodb.conditions import Key
def check_message_id(message_id):
dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table('m_jira_tickets')
_log('checking message_id availability ' + message_id)
try:
response = table.get_item(Key={'messageid': message_id})
_log("Scanning table");
_log(response)
except ClientError as e:
_log(e.response['Error']['Message'])
return False
if "Item" in response :
_log(response["Item"]["ticketid"])
return response["Item"]["ticketid"]
else :
return False
def create_record(
message_id,
ticket_id,
label_to
):
dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table('m_jira_tickets')
_log('create record')
try:
response = table.put_item(Item={
'messageid': message_id,
'ticketid': ticket_id,
'project': "12655",
'label_to': label_to,
})
_log(response)
except ClientError as e:
_log(e.response['Error']['Message'])
return False
else:
return True
def _log(str):
print(str)
#!/usr/bin/python
# -*- coding: utf-8 -*-
import json
import email
import botocore
from botocore.vendored import requests
from requests.auth import HTTPBasicAuth
from email.utils import parseaddr
import base64
from pprint import pprint
import db
## constant
if_emails = ["example@example.com"] # create only if email matches in
## JIRA API URL
JIRA_URL = "https://<cloud>.atlassian.net/rest/api/3/issue"
## JIRA basic auth token
## once can create this token from user profile
AUTH = HTTPBasicAuth("<username>", "<app token>")
HEADERS = {
"Accept": "application/json",
"Content-Type": "application/json"
}
def lambda_handler(event, context):
base64_bytes = event["data"].encode('ascii')
message_bytes = base64.b64decode(base64_bytes)
raw_email = message_bytes.decode('ascii')
_log(raw_email)
message = email.message_from_string(raw_email)
text_plain = None
text_html = None
_log("Parsing Email")
for part in message.walk():
if part.get_content_type() == 'text/plain' and text_plain is None:
text_plain = part.get_payload()
if part.get_content_type() == 'text/html' and text_html is None:
text_html = part.get_payload()
parsed_email_object = {
'to': message.get_all("To", []),
'from': message.get_all('From',[]),
'delivered_to': message.get('Delivered-To'),
'subject': message.get('Subject'),
'message_id': message.get('Message-ID'),
'cc': message.get_all('cc',[]),
'date':message.get('Date'),
'references':message.get_all('References',[]),
'text': text_plain
}
_log(parsed_email_object)
# check if we should create ticket / comment
label_to = _should_create(parsed_email_object);
if not label_to:
_log("Skipping as to address not found for ticket creation mapping")
exit();
else:
parsed_email_object["label_to"]=label_to;
# check if we need to add comment or create ticket
ticket_id = _should_create_comment(parsed_email_object);
status = False;
if ticket_id:
status = jira_comment(parsed_email_object, ticket_id)
else:
status = jira_ticket(parsed_email_object)
return {
'statusCode': 200,
'body': status
}
def _should_create(message):
for to in email.utils.getaddresses(message["to"]):
if to[1] in if_emails:
return to[1]
for cc in email.utils.getaddresses(message["cc"]):
if cc[1] in if_emails:
return cc[1]
## default if mapping not defined
return False
def _should_create_comment(message):
if not message["references"]:
return False
else:
# check if we have any association for message id
_log("checking references");
for ref in email.utils.getaddresses(message["references"]):
_log(ref);
ref = '<'+ ref[1] +'>'
ticket_id = db.check_message_id(ref)
if ticket_id :
_log("Got ticket id "+ticket_id)
return ticket_id
## JIRA ticket creation
def jira_ticket(message):
desc = """
FROM : {}
TO : {}
CC : {}
Date : {}
Message :
{}
"""
try:
data = {
"fields": {
"project": {"id": "12655"},
"issuetype": {"id": "10021"},
"summary": message["subject"],
"components": [],
"description": {
"version": 1,
"type": "doc",
"content": [
{"type": "paragraph", "content": [{"type": "text", "text": desc.format(message["from"],message["to"],message["cc"],message["date"],message["text"])}]}
],
},
"fixVersions": [],
"priority": {
"id": "3"
},
"customfield_10004": 1,
"labels": [message["label_to"]],
}
}
ticket_id = 0;
payload = json.dumps(data)
_log("Starting Jira Ticket Request");
_log("Payload " + payload);
response = requests.request(
"POST",
JIRA_URL,
data=payload,
headers=HEADERS,
auth=AUTH
)
_log("Response " + response.text)
if response.status_code == 201 :
res=json.loads(response.text)
ticket_id = res["id"]
_log("Ticket id : "+ ticket_id);
db.create_record(message["message_id"], ticket_id, message["label_to"])
else:
_log("ticket creation failed. status :" + str(response.status_code))
except Exception as e:
_log("Error" + str(e));
def jira_comment(message, ticket_id):
if not ticket_id:
return False;
comment_url = JIRA_URL+"/"+ticket_id+"/comment"
desc = """
FROM : {}
TO : {}
CC : {}
Date : {}
Message :
{}
"""
try:
data = {
"body": {
"content": [
{
"type": "paragraph",
"content": [
{
"type": "text",
"text": desc.format(
message["from"],
message["to"],
message["cc"],
message["date"],
message["text"],
),
}
],
}
],
"version": 1,
"type": "doc",
}
}
payload = json.dumps(data)
_log("Starting Jira Comment Request");
_log("Payload " + payload);
response = requests.request(
"POST",
comment_url,
data=payload,
headers=HEADERS,
auth=AUTH
)
_log("Response " + response.text)
if response.status_code == 201 :
res=json.loads(response.text)
ticket_id = res["id"]
_log("Ticket id : "+ ticket_id);
db.create_record(message["message_id"], ticket_id,'')
else:
_log("ticket creation failed. status :" + str(response.status_code))
except Exception as e:
_log("Error" + str(e));
def _log(msg):
print(msg)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment