Ashhar commited on
Commit
4e472cd
1 Parent(s): e6dd180

add email stats

Browse files
Files changed (3) hide show
  1. app.py +20 -12
  2. requirements.txt +2 -0
  3. tools.py +123 -10
app.py CHANGED
@@ -8,7 +8,7 @@ import re
8
  import random
9
  import string
10
  from transformers import AutoTokenizer
11
- from tools import toolsInfo
12
 
13
  from dotenv import load_dotenv
14
  load_dotenv()
@@ -85,9 +85,9 @@ Check with them what they would like to change in the variation.
85
 
86
  # Once the mail is finalized. You ask the user for all the missing placeholder values to write the final mail.
87
 
88
- # Once the placeholder values are available in the final email, you ask for the recipient email ID.
89
 
90
- # Once you have the final mail with placeholder values and recipient exact email ID, you send the email to this id.
91
  Dont send email until you have received a valid email from user.
92
 
93
  # You congratulate the user and ask if he would like to save this email as a template. If he agrees, save this template in Google Sheet.
@@ -155,6 +155,10 @@ st.markdown(
155
  font-family: 'Courier New', Courier, monospace; /* Monospace font */
156
  }
157
 
 
 
 
 
158
  </style>
159
  """,
160
  unsafe_allow_html=True
@@ -195,6 +199,9 @@ if "buttonValue" not in st.session_state:
195
  if "startMsg" not in st.session_state:
196
  st.session_state.startMsg = ""
197
 
 
 
 
198
  st.session_state.toolResponseDisplay = {}
199
 
200
 
@@ -235,15 +242,6 @@ def __showToolResponse(toolResponseDisplay: dict):
235
  st.markdown(msg)
236
 
237
 
238
- def __process_stream_chunk(chunk):
239
- delta = chunk.choices[0].delta
240
- if delta.content:
241
- return delta.content
242
- elif delta.tool_calls:
243
- return delta.tool_calls[0]
244
- return None
245
-
246
-
247
  def __addToolCallToMsgs(toolCall: dict):
248
  st.session_state.messages.append(
249
  {
@@ -442,3 +440,13 @@ if prompt := (st.chat_input() or st.session_state["buttonValue"] or st.session_s
442
  "role": "assistant",
443
  "content": response,
444
  })
 
 
 
 
 
 
 
 
 
 
 
8
  import random
9
  import string
10
  from transformers import AutoTokenizer
11
+ from tools import toolsInfo, showEmailStats
12
 
13
  from dotenv import load_dotenv
14
  load_dotenv()
 
85
 
86
  # Once the mail is finalized. You ask the user for all the missing placeholder values to write the final mail.
87
 
88
+ # After the placeholder values are available in the final email, you ask for the recipient email ID.
89
 
90
+ # Once you have the final mail with placeholder values and recipient exact email ID, you send this final well formatted mail to the email ID.
91
  Dont send email until you have received a valid email from user.
92
 
93
  # You congratulate the user and ask if he would like to save this email as a template. If he agrees, save this template in Google Sheet.
 
155
  font-family: 'Courier New', Courier, monospace; /* Monospace font */
156
  }
157
 
158
+ div[aria-label="dialog"] {
159
+ width: 90vw;
160
+ }
161
+
162
  </style>
163
  """,
164
  unsafe_allow_html=True
 
199
  if "startMsg" not in st.session_state:
200
  st.session_state.startMsg = ""
201
 
202
+ if "emailSent" not in st.session_state:
203
+ st.session_state.emailSent = False
204
+
205
  st.session_state.toolResponseDisplay = {}
206
 
207
 
 
242
  st.markdown(msg)
243
 
244
 
 
 
 
 
 
 
 
 
 
245
  def __addToolCallToMsgs(toolCall: dict):
246
  st.session_state.messages.append(
247
  {
 
440
  "role": "assistant",
441
  "content": response,
442
  })
443
+
444
+
445
+ @st.dialog("Email Delivery Stats", width="large")
446
+ def emailStats():
447
+ showEmailStats()
448
+
449
+
450
+ with st.sidebar:
451
+ if st.session_state.emailSent:
452
+ st.button("Email Delivery Stats", on_click=emailStats)
requirements.txt CHANGED
@@ -5,3 +5,5 @@ gradio_client
5
  oauth2client
6
  gspread
7
  sendgrid
 
 
 
5
  oauth2client
6
  gspread
7
  sendgrid
8
+ plotly
9
+ streamlit_extras
tools.py CHANGED
@@ -3,16 +3,22 @@ import gspread
3
  import os
4
  import json
5
  from sendgrid import SendGridAPIClient
6
- from sendgrid.helpers.mail import Mail
 
 
7
 
8
  from dotenv import load_dotenv
9
  load_dotenv()
10
 
11
  GCP_JSON_KEY = os.environ.get("GCP_JSON_KEY")
 
 
12
  MY_EMAIL = "ashharakhlaque@gmail.com"
 
13
  TEMPLATE_COL_NAME = "Template"
14
 
15
- sg = SendGridAPIClient(os.environ.get('SENDGRID_API_KEY'))
 
16
 
17
 
18
  def saveProfileDetailsInGSheet(
@@ -94,21 +100,40 @@ def sendEmail(
94
  subject: str,
95
  htmlContent: str
96
  ):
97
- message = Mail(
98
- from_email=MY_EMAIL,
99
- to_emails=toEmail,
100
- subject=subject,
101
- html_content=htmlContent,
102
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
103
  try:
104
- sg.send(message)
 
 
105
  return {
106
  "response": "Email sent",
107
  "display": {
108
  "text": f"`Email sent to {toEmail}`",
109
  "icon": "icons/mail.png",
110
  }
111
- }
112
  except Exception as e:
113
  print(e.message)
114
  return {
@@ -210,3 +235,91 @@ toolsInfo = {
210
  },
211
 
212
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3
  import os
4
  import json
5
  from sendgrid import SendGridAPIClient
6
+ import streamlit as st
7
+ import pandas as pd
8
+ import plotly.express as px
9
 
10
  from dotenv import load_dotenv
11
  load_dotenv()
12
 
13
  GCP_JSON_KEY = os.environ.get("GCP_JSON_KEY")
14
+ SENDGRID_API_KEY = os.environ.get("SENDGRID_API_KEY")
15
+
16
  MY_EMAIL = "ashharakhlaque@gmail.com"
17
+ MY_NAME = "Ashhar Akhlaque"
18
  TEMPLATE_COL_NAME = "Template"
19
 
20
+ print(SENDGRID_API_KEY)
21
+ sg = SendGridAPIClient(SENDGRID_API_KEY)
22
 
23
 
24
  def saveProfileDetailsInGSheet(
 
100
  subject: str,
101
  htmlContent: str
102
  ):
103
+ data = {
104
+ "personalizations": [{
105
+ "to": [
106
+ {
107
+ "email": toEmail,
108
+ }
109
+ ],
110
+ "subject": subject
111
+ }],
112
+ "from": {
113
+ "email": MY_EMAIL,
114
+ "name": MY_NAME
115
+ },
116
+ "reply_to": {
117
+ "email": MY_EMAIL,
118
+ "name": MY_NAME
119
+ },
120
+ "content": [{
121
+ "type": "text/html",
122
+ "value": htmlContent
123
+ }]
124
+ }
125
+
126
  try:
127
+ response = sg.client.mail.send.post(request_body=data)
128
+ print(f"{response.status_code=}")
129
+ st.session_state["emailSent"] = True
130
  return {
131
  "response": "Email sent",
132
  "display": {
133
  "text": f"`Email sent to {toEmail}`",
134
  "icon": "icons/mail.png",
135
  }
136
+ }
137
  except Exception as e:
138
  print(e.message)
139
  return {
 
235
  },
236
 
237
  }
238
+
239
+
240
+ def showEmailStats():
241
+ params = {'start_date': '2024-09-07'}
242
+
243
+ response = sg.client.stats.get(
244
+ query_params=params
245
+ )
246
+
247
+ stats = json.loads(response.body)
248
+
249
+ # Convert stats to a pandas DataFrame
250
+ df = pd.DataFrame([
251
+ {
252
+ 'date': item['date'],
253
+ **item['stats'][0]['metrics']
254
+ } for item in stats
255
+ ])
256
+ df['date'] = pd.to_datetime(df['date'])
257
+
258
+ # Display overall stats
259
+ st.subheader("Email Campaign Overview")
260
+
261
+ col1, col2, col3, col4, col5 = st.columns([1, 1, 1, 1, 4])
262
+ col1.metric("Total Sent", df['requests'].sum())
263
+ col2.metric("Delivered", df['delivered'].sum())
264
+ col3.metric("Opens", df['opens'].sum())
265
+ col4.metric("Bounces", df['bounces'].sum())
266
+
267
+ col1, col2, col3 = st.columns([3, 1, 3])
268
+
269
+ # Create line chart for key metrics
270
+ figLine = px.line(
271
+ df,
272
+ x='date',
273
+ y=['delivered', 'opens', 'unique_opens', 'bounces'],
274
+ title='Key Metrics Over Time',
275
+ color_discrete_map={ # Define custom colors
276
+ 'delivered': 'green',
277
+ 'opens': 'blue',
278
+ 'unique_opens': 'purple',
279
+ 'bounces': 'red'
280
+ },
281
+ labels={'date': 'Date', 'value': 'Count'},
282
+ markers=True,
283
+ height=400,
284
+ )
285
+ figLine.update_layout(
286
+ legend=dict(
287
+ orientation="h", # Horizontal orientation
288
+ yanchor="bottom",
289
+ y=1.02, # Position above the chart
290
+ xanchor="right",
291
+ x=1,
292
+ title=None, # Remove legend title
293
+ )
294
+ )
295
+ col1.plotly_chart(figLine)
296
+
297
+ # Create bar chart for email status
298
+ dfStatus = df[['delivered', 'bounces', 'invalid_emails']].sum().reset_index()
299
+ dfStatus.columns = ['status', 'count']
300
+ figBar = px.bar(
301
+ dfStatus,
302
+ x='status',
303
+ y='count',
304
+ title='Email Status Distribution',
305
+ color='status', # Use status for color
306
+ color_discrete_map={ # Define custom colors
307
+ 'delivered': 'green',
308
+ 'bounces': 'red',
309
+ 'invalid_emails': 'orange'
310
+ },
311
+ labels={'status': 'Status', 'count': 'Count'},
312
+ text='count',
313
+ height=400,
314
+ )
315
+ figBar.update_layout(
316
+ legend=dict(
317
+ orientation="h", # Horizontal orientation
318
+ yanchor="bottom",
319
+ y=1.02, # Position above the chart
320
+ xanchor="right",
321
+ x=1,
322
+ title=None, # Remove legend title
323
+ )
324
+ )
325
+ col3.plotly_chart(figBar)