1

Currently I had developed a script that will read incoming/latest email and filter the email based on certain criteria such as email subject and text. When user select subject or text, they are able to choose which condition they want to filter the email (Equals, Does not contain etc).

My Problem I have a demo website that will let user to add different conditions to filter the email. But now my script can only handle one condition and execute at one time . How can I make my script to detect there are multiple condition and filter the email based on the multiple rules ? Im using Django to do my website

My previous script: After user click on OK, the script in view.py will directly be executed and it will parse the email based on the current condition only

enter image description here

What I trying to achieve: I had modify my html template and it will continuously letting user to add few conditions rather than just execute one condition only. Example: When user choose the parameter etc and click OK and new row will be store and the script will parse the email based on how many rules that user want to be parse. (After clicking submit the script will only be triggered when all the rules are met)

enter image description here

Expected output (based on the above picture) The system able to parse incoming email with these two rules which are Email subject must equal to test and the text must contain text contain

Possible solution Is it able to dynamically add the If Else statement when there are new rules coming in? and count until the last row of the rules then just execute.

My py script (This code is previous version, it only able to execute one time when user click on OK)

from django.http import HttpResponse
import datetime
import email
import imaplib
import mailbox
import smtplib

def index(request):

    return render(request,'DemoApp/hi.html')

def send(request):
    EMAIL_ACCOUNT = "[email protected]"
    PASSWORD = "xxx"

    mail = imaplib.IMAP4_SSL('imap.gmail.com')
    mail.login(EMAIL_ACCOUNT, PASSWORD)
    mail.list()
    mail.select('inbox')
    result, data = mail.uid('search', None, "UNSEEN")  # (ALL/UNSEEN)
    i = len(data[0].split())

    for x in range(i):
        latest_email_uid = data[0].split()[x]
        result, email_data = mail.uid('fetch', latest_email_uid, '(RFC822)')
        # result, email_data = conn.store(num,'-FLAGS','\\Seen')
        # this might work to set flag to seen, if it doesn't already
        raw_email = email_data[0][1]
        raw_email_string = raw_email.decode('utf-8')
        email_message = email.message_from_string(raw_email_string)

        # Header Details
        date_tuple = email.utils.parsedate_tz(email_message['Date'])
        if date_tuple:
            local_date = datetime.datetime.fromtimestamp(email.utils.mktime_tz(date_tuple))
            local_message_date = "%s" % (str(local_date.strftime("%a, %d %b %Y %H:%M:%S")))
        email_from = str(email.header.make_header(email.header.decode_header(email_message['From'])))
        email_to = str(email.header.make_header(email.header.decode_header(email_message['To'])))
        subject = str(email.header.make_header(email.header.decode_header(email_message['Subject'])))

        # Body details
        for part in email_message.walk():

            if part.get_content_type() == "text/plain":
                body = part.get_payload(decode=True)


                #Get all value from
                ParameterGet = str(request.POST.get('Parameter', None))
                ConditionGet = str(request.POST.get('Condition', None))
                valuetomatch = str(request.POST["valuetomatch"])

                def emailSendDetails():
                    server = smtplib.SMTP('smtp.gmail.com', 587)
                    server.starttls()
                    server.login(EMAIL_ACCOUNT, PASSWORD)
                    msg = "ALERT NOTICE!"
                    server.sendmail(EMAIL_ACCOUNT, "[email protected]", msg)
                    server.quit()

                #<----------------Parameter---------------->
                #Subject
                if ParameterGet == "Subject":
                    # <----------------Condition---------------->
                    #Equals
                    if ConditionGet == "Equals":
                        if valuetomatch == subject:
                            server = smtplib.SMTP('smtp.gmail.com', 587)
                            server.starttls()
                            server.login(EMAIL_ACCOUNT, PASSWORD)
                            msg = "subject equals!"
                            server.sendmail(EMAIL_ACCOUNT, "[email protected]", msg)
                            server.quit()
                        else:
                            print("no email");

                    # Contain
                    if ConditionGet == "Contain":
                        if valuetomatch in subject:
                            server = smtplib.SMTP('smtp.gmail.com', 587)
                            server.starttls()
                            server.login(EMAIL_ACCOUNT, PASSWORD)
                            msg = "subject contain!"
                            server.sendmail(EMAIL_ACCOUNT, "[email protected]", msg)
                            server.quit()
                        else:
                            print("no email");

                    # Does not contain
                    if ConditionGet == "NotContain":
                        if valuetomatch not in subject:
                            server = smtplib.SMTP('smtp.gmail.com', 587)
                            server.starttls()
                            server.login(EMAIL_ACCOUNT, PASSWORD)
                            msg = "subject not contain!"
                            server.sendmail(EMAIL_ACCOUNT, "[email protected]", msg)
                            server.quit()
                        else:
                            print("no email");


                # <----------------Parameter---------------->
                #Text
                if ParameterGet == "Text":
                    # <----------------Condition---------------->
                    # Equals
                    if ConditionGet == "Equals":

                        if valuetomatch == body.decode('utf-8').rstrip():
                            server = smtplib.SMTP('smtp.gmail.com', 587)
                            server.starttls()
                            server.login(EMAIL_ACCOUNT, PASSWORD)
                            msg = "text equals!"
                            server.sendmail(EMAIL_ACCOUNT, "[email protected]", msg)
                            server.quit()
                        else:
                            print("no email");

                    # Contain
                    if ConditionGet == "Contain":
                        if valuetomatch in body.decode('utf-8'):
                            server = smtplib.SMTP('smtp.gmail.com', 587)
                            server.starttls()
                            server.login(EMAIL_ACCOUNT, PASSWORD)
                            msg = "text contain!"
                            server.sendmail(EMAIL_ACCOUNT, "[email protected]", msg)
                            server.quit()
                        else:
                            print("no email");

                    # Does not contain
                    if ConditionGet == "NotContain":
                        if valuetomatch not in body.decode('utf-8'):
                            server = smtplib.SMTP('smtp.gmail.com', 587)
                            server.starttls()
                            server.login(EMAIL_ACCOUNT, PASSWORD)
                            msg = "text notcontain!"
                            server.sendmail(EMAIL_ACCOUNT, "[email protected]", msg)
                            server.quit()
                        else:
                            print("no email");
            else:
                continue


    return render(request, 'DemoApp/hi.html', {'key': "Send successfully"})

The same script but it doesn't link to the Html or django template, its all hard coded parameter But it help for debugging

import datetime
import email
import imaplib
import mailbox
import smtplib

while True:
    EMAIL_ACCOUNT = "[email protected]"
    PASSWORD = "xxx"

    mail = imaplib.IMAP4_SSL('imap.gmail.com')
    mail.login(EMAIL_ACCOUNT, PASSWORD)
    mail.list()
    mail.select('inbox')
    result, data = mail.uid('search', None, "UNSEEN")  # (ALL/UNSEEN)
    i = len(data[0].split())

    for x in range(i):
        latest_email_uid = data[0].split()[x]
        result, email_data = mail.uid('fetch', latest_email_uid, '(RFC822)')
        # result, email_data = conn.store(num,'-FLAGS','\\Seen')
        # this might work to set flag to seen, if it doesn't already
        raw_email = email_data[0][1]
        raw_email_string = raw_email.decode('utf-8')
        email_message = email.message_from_string(raw_email_string)

        # Header Details
        date_tuple = email.utils.parsedate_tz(email_message['Date'])
        if date_tuple:
            local_date = datetime.datetime.fromtimestamp(email.utils.mktime_tz(date_tuple))
            local_message_date = "%s" % (str(local_date.strftime("%a, %d %b %Y %H:%M:%S")))
        email_from = str(email.header.make_header(email.header.decode_header(email_message['From'])))
        email_to = str(email.header.make_header(email.header.decode_header(email_message['To'])))
        subject = str(email.header.make_header(email.header.decode_header(email_message['Subject'])))

        # Body details
        for part in email_message.walk():

            if part.get_content_type() == "text/plain":
                body = part.get_payload(decode=True)
                print("From:", email_from)

                print("Email To:", email_to)
                print("date:", local_message_date)
                print("Subject:", subject)
                print("body:", body.decode('utf-8'))

                '''If subject have "Consent" it will send specific email to recipient'''
                if "Consent" in subject:
                    server = smtplib.SMTP('smtp.gmail.com', 587)
                    server.starttls()
                    server.login(EMAIL_ACCOUNT, PASSWORD)

                    msg = "ALERT NOTICE!"
                    server.sendmail(EMAIL_ACCOUNT, "[email protected]", msg)
                    server.quit()
                else:
                    print("no email");

            else:
                continue

My Current Html template

<!DOCTYPE html>
<html lang="en">
<html>
<head>
    <link href="https://fonts.googleapis.com/css?family=Quicksand:300,500" rel="stylesheet">
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"
          integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

    <style>


.buttonSubmit{
background-color: #4CAF50;
  border: none;
  color: white;
  padding: 15px 32px;
  text-align: center;
  text-decoration: none;
  display: inline-block;
  font-size: 16px;
  margin: 4px 2px;
  cursor: pointer;
}




table {
  font-family: arial, sans-serif;
  border-collapse: collapse;
  width: 100%;
}

td, th {
  border: 1px solid #dddddd;
  text-align: left;
  padding: 8px;
}

tr:nth-child(even) {
  background-color: #dddddd;
}

body {font-family: 'Quicksand', sans-serif;}
.button {
  border-radius: 50px;
  background-color:  #ff9633;
  border: none;
  color: #FFFFFF;
  text-align: center;
  font-size: 15px;
  padding: 10px;
  width: 80px;
  transition: all 0.5s;
  cursor: pointer;
  margin: 5px;
  margin-left:500px;
}

.button span {
  cursor: pointer;
  display: inline-block;
  position: relative;
  transition: 0.5s;
}

.button span:after {
  content: '\00bb';
  position: absolute;
  opacity: 0;
  top: 0;
  right: -20px;
  transition: 0.5s;
}

.button:hover span {
  padding-right: 25px;
}

.button:hover span:after {
  opacity: 1;
  right: 0;
}

/* The Modal (background) */
.modal {
  display: none; /* Hidden by default */
  position: fixed; /* Stay in place */
  z-index: 1; /* Sit on top */
  padding-top: 100px; /* Location of the box */
  left: 0;
  top: 0;
  width: 100%; /* Full width */
  height: 100%; /* Full height */
  overflow: auto; /* Enable scroll if needed */
  background-color: rgb(0,0,0); /* Fallback color */
  background-color: rgba(0,0,0,0.4); /* Black w/ opacity */
}

/* Modal Content */
.modal-content {
  position: relative;
  background-color: #fefefe;
  margin: auto;
  padding: 0;
  border: 1px solid #888;
  width: 45%;

  box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2),0 6px 20px 0 rgba(0,0,0,0.19);
  -webkit-animation-name: animatetop;
  -webkit-animation-duration: 0.4s;
  animation-name: animatetop;
  animation-duration: 0.4s
}


/* Add Animation */
@-webkit-keyframes animatetop {
  from {top:-300px; opacity:0}
  to {top:0; opacity:1}
}

@keyframes animatetop {
  from {top:-300px; opacity:0}
  to {top:0; opacity:1}
}

/* The Close Button */
.close {
  color: white;
  float: right;
  font-size: 28px;
  font-weight: bold;
}

.close:hover,
.close:focus {
  color: #000;
  text-decoration: none;
  cursor: pointer;
}

.modal-header {
  padding: 2px 16px;
  background-color: #ff9633;
  color: white;
}

.modal-body {padding: 2px 16px;}

.modal-footer {
  padding: 2px 16px;
  background-color: #ff9633;
  color: white;
}

ul {
  list-style-type: none;
  margin: 0;
  padding: 0;
  overflow: hidden;
  background-color: #ff9633;
}

li {
  float: left;
}

li a {
  display: block;
  color: white;
  text-align: center;
  padding: 14px 16px;
  text-decoration: none;
}

li a:hover {
  background-color:
#fa7d34;
}






    </style>
</head>
<body>


<ul>

    <li>
        <div id="myBtn1"><a href="#AddCon">Alert Policies</a></div>
    </li>
    <li><a href="#contact">Test3</a></li>
    <li><a href="#about">Test4</a></li>
</ul>


<!-- The Modal -->
<div id="myModal" class="modal">
    <!-- Modal content -->
    <div class="modal-content">
        <div class="modal-header">
            <span class="close">&times;</span>
            <h2>Alert Policies</h2>
        </div>
        <div class="modal-body">

            <p style="font-size:14px">Please select an event parameter as well as the condition type and value that
                apply.</p>

            <!-- parameter drop down -->
            <form method="post">

                <label for="Parameter"> <b style="font-size:13px"> Event parameter to evaluate </b></label>
                <select name="Parameter" id="Parameter" style="width:340px; font-family: 'Quicksand', sans-serif;">
                    <option disabled selected value>select a parameter</option>
                    <option value="Subject">Subject</option>
                    <option value="Text">Text</option>

                </select>
                <br><br>

                <label for="Condition"> <b style="font-size:13px"> Type of condition </b></label>
                <select name="Condition" id="Condition"
                        style="width:340px; margin-left:69px; font-family: 'Quicksand', sans-serif;">
                    <option disabled selected value>select a condition</option>
                    <option value="Equals">Equals</option>
                    <option value="Contain">Contain</option>
                    <option value="NotContain">Does not contain</option>

                </select>
                <br><br>

                <label for="valuetomatch"> <b style="font-size:13px"> Value to match</b></label>
                <input type="text" id="valuetomatch" name="valuetomatch"
                       style="width:333px; margin-left:80px; font-family: 'Quicksand', sans-serif;">
                <br>
                <br>
            </form>
            <button class="button"><span>OK</span></button>


        </div>


    </div>

</div>
<table id="myTable">

    <tr>
        <th>Event Parameter</th>
        <th>Condition</th>
        <th>Value to match</th>
        <th>Action</th>

    </tr>

</table>
<br>

<a href="#" class="buttonSubmit">Submit</a>




<script>

//add tablebox
$(document).ready(function(){
    $(".button").on('click', function () {

   para = document.getElementById("Parameter").value;
   condi = document.getElementById("Condition").value;
   value2match = document.getElementById("valuetomatch").value;

  if (para && condi && value2match !== null) {
  var table = document.getElementById("myTable");
  var row = table.insertRow(-1);
  var cell1 = row.insertCell(0);
  var cell2 = row.insertCell(1);
  var cell3 = row.insertCell(2);
  var cell4 = row.insertCell(3);

  cell1.innerHTML = document.getElementById("Parameter").value;
  cell2.innerHTML = document.getElementById("Condition").value;
  cell3.innerHTML = document.getElementById("valuetomatch").value;
  cell4.innerHTML = '<button  class = "del_img "onClick="delSpec(this)">Delete</button> </div>';

  //close the modal
  modal.style.display = "none";
}else
{
 alert("All the input box cannot be empty!");
}

    });
});

function delSpec(node)
    {
    r=node.parentNode.parentNode;
    r.parentNode.removeChild(r);
    }

// Get the modal
var modal = document.getElementById("myModal");

// Get the button that opens the modal
var btn = document.getElementById("myBtn1");

// Get the <span> element that closes the modal
var span = document.getElementsByClassName("close")[0];

// When the user clicks the button, open the modal
btn.onclick = function() {
  modal.style.display = "block";
}


// When the user clicks anywhere outside of the modal, close it
window.onclick = function(event) {
  if (event.target == modal) {
    modal.style.display = "none";
  }
}






</script>

</body>
</html>
6
  • Hi, Please provide a minimal reproducible example. This piece of code is large. Commented May 20, 2021 at 6:31
  • @Sujay hi thanks for the respond, yes im trying to figure out which part should I modify haha. Cause everything in the code is important Commented May 20, 2021 at 6:32
  • @Sujay I had edit a new code snippet for the python script. It can be run without relating to html or django. The script is just hard coded parameter which will only be triggered if the subject has Consent in it. Commented May 20, 2021 at 6:37
  • 1
    I am not an expert in py. But use of dynamic filter (where conditions) is common across languages. In summary, you have the if else statement inside a while loop and call the loop based on number of filters (usually stored in an array). Commented May 20, 2021 at 6:39
  • 1
    If/elses are abstracted using dictionaries Commented May 20, 2021 at 6:43

2 Answers 2

1

This problem looks interesting. Let me give my try,

I can see there are only three conditions that need to be performed. So let make a dictionary out of it:

con = {
"Equals": "==",
"Contain": "in",
"NotContain": "not in"
}

I can see you have the required values ready in hand here:

#Get all value from
ParameterGet = str(request.POST.get('Parameter', None))
ConditionGet = str(request.POST.get('Condition', None))
valuetomatch = str(request.POST["valuetomatch"])

Let's take the for loop to iterate the table alert policies rows for iteration,

con = {
"Equals": "==",
"Contain": "in",
"NotContain": "not in"
}

for each_row in rows:
  ***your other logic goes here***
  ParameterGet = str(request.POST.get('Parameter', None))
  ConditionGet = str(request.POST.get('Condition', None))
  valuetomatch = str(request.POST["valuetomatch"])
  text = "body.decode('utf-8').rstrip()"
  current_condition = "(valuetomatch "+ con[ConditionGet] + " " + ParameterGet.lower() + ")"
  if eval(current_condition):
          server = smtplib.SMTP('smtp.gmail.com', 587)
          server.starttls()
          server.login(EMAIL_ACCOUNT, PASSWORD)
          msg = "subject not contain!"
          server.sendmail(EMAIL_ACCOUNT, "[email protected]", msg)
          server.quit()
  else:
          print("no email");

OUTPUT:

>>> con = {
"Equals": "==",
"Contain": "in",
"NotContain": "not in"
}
>>> valuetomatch = "hi"
>>> ConditionGet = "Contain"
>>> ParameterGet = "Subject"
>>> subject = "hi"
>>> current_condition = "(valuetomatch "+ con[ConditionGet] + " " + ParameterGet.lower() + ")"
>>> current_condition
'(valuetomatch in subject)'
>>> eval(current_condition)
True

Check eval for reference.

Sign up to request clarification or add additional context in comments.

6 Comments

HI thanks for the respond, looking through your answer it make sense ! Tomorrow i will try to implement your way. Btw can i know why you need to put parameterget to lower() ? Other than that, for each_row in rows you mean by the html table ?
For lower() usage, since we named the variables as subject and text in our code and we're getting ParameterGet as "Subject" and "Text", hence converting it to lowercase. And yeah, I meant the HTML table only.
Since i already successfully to get the array list, I will prefer it read from an array list rather than rows. Btw did you tried your code? does it workable?
Mark my answer as approved if it really helps you. Else feel free to update this with the right answer in case if some other solution works for you.
Actually I need the 2 rules to be meet before sending the alert message to someone. But if you put ` current_condition` inside the for loop, does it mean it only read the first rules and execute it ?
|
0

You could try something like this in server side:

# What you get from frontend
arr=[["Subject","Equals","test"],["Text","Contain","Testing 1 2 3"],["Text","Contain","rhrhj"]]
email_message = email.message_from_string(raw_email_string)
subject = str(email.header.make_header(email.header.decode_header(email_message['Subject'])))

# Dict with mapping between patterns and objects
to_compare = {
    'Subject': subject,
    'Text': email_message,
}

# Returns right object between email_message or subject
def get_compare(target, to_compare):
    try:
        return to_compare[target]
    except:
        raise Exception(f"{target} not found in comparable elements.")
    
# Loop over arr, perform checks and do actions
for alert in arr:
    if arr[1] == 'Equals':
        if get_compare(arr[0]) == arr[3]:
            # Do something
        
    elif arr[1] == 'Contain':
        if arr[3] in get_compare(arr[0]):
            # Do something
        
    elif arr[1] == 'NotContain':
        if arr[3] not in get_compare(arr[0]):
            # Do something
        
    else:
        raise Exception(f"{arr[1]} does not belong to recognize operators.")

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.