-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Add exposure notification model * Add stories/background with notification control logic * Add backend/emails/content/py to flake8 ignored files * Add email sender based on aws ses see https://docs.aws.amazon.com/ses/latest/DeveloperGuide/examples-send-using-smtp.html * Notify contacts only if user is sick and tested positive
- Loading branch information
1 parent
a1879e6
commit 9d7b15c
Showing
8 changed files
with
381 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
70 changes: 70 additions & 0 deletions
70
backend/alembic/versions/a31bfe8eba6b_create_exposure_notifications_model.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
"""create exposure notifications model | ||
Revision ID: a31bfe8eba6b | ||
Revises: 8bc2e50b6d22 | ||
Create Date: 2020-07-02 19:19:19.971471 | ||
""" | ||
from alembic import op | ||
import sqlalchemy as sa | ||
|
||
|
||
# revision identifiers, used by Alembic. | ||
revision = "a31bfe8eba6b" | ||
down_revision = "8bc2e50b6d22" | ||
branch_labels = None | ||
depends_on = None | ||
|
||
|
||
def upgrade(): | ||
# ### commands auto generated by Alembic - please adjust! ### | ||
op.create_table( | ||
"exposure_notifications", | ||
sa.Column("id", sa.Integer(), nullable=False), | ||
sa.Column("created_at", sa.DateTime(), nullable=True), | ||
sa.Column("updated_at", sa.DateTime(), nullable=True), | ||
sa.Column("email", sa.String(length=128), nullable=True), | ||
sa.Column("notified_at", sa.Date(), nullable=True), | ||
sa.PrimaryKeyConstraint("id"), | ||
sa.UniqueConstraint("email"), | ||
) | ||
op.create_index( | ||
op.f("ix_exposure_notifications_id"), | ||
"exposure_notifications", | ||
["id"], | ||
unique=False, | ||
) | ||
op.create_table( | ||
"story_notifications", | ||
sa.Column("id", sa.Integer(), nullable=False), | ||
sa.Column("created_at", sa.DateTime(), nullable=True), | ||
sa.Column("updated_at", sa.DateTime(), nullable=True), | ||
sa.Column("story_id", sa.Integer(), nullable=True), | ||
sa.Column("notification_id", sa.Integer(), nullable=True), | ||
sa.ForeignKeyConstraint( | ||
["notification_id"], ["exposure_notifications.id"], | ||
), | ||
sa.ForeignKeyConstraint(["story_id"], ["stories.id"],), | ||
sa.PrimaryKeyConstraint("id"), | ||
) | ||
op.create_index( | ||
op.f("ix_story_notifications_id"), | ||
"story_notifications", | ||
["id"], | ||
unique=False, | ||
) | ||
# ### end Alembic commands ### | ||
|
||
|
||
def downgrade(): | ||
# ### commands auto generated by Alembic - please adjust! ### | ||
op.drop_index( | ||
op.f("ix_story_notifications_id"), table_name="story_notifications" | ||
) | ||
op.drop_table("story_notifications") | ||
op.drop_index( | ||
op.f("ix_exposure_notifications_id"), | ||
table_name="exposure_notifications", | ||
) | ||
op.drop_table("exposure_notifications") | ||
# ### end Alembic commands ### |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
EXPOSURE_NOTIFICATION_SUBJECT = "COVID-19 - Important notification" | ||
|
||
EXPOSURE_NOTIFICATION_TEXT_CONTENT = """ | ||
Hello. This is a notice from Oasis, a citizen-led global community working to stop the spread of COVID-19. | ||
Oasis community volunteers document their symptoms and COVID-19 test results on the Oasis platform. | ||
In addition, they can provide contact information of people whom they have been near and who may have been exposed to the virus. | ||
This notification is to let you know that you may have been exposed to the COVID-19 virus (https://www.cdc.gov/coronavirus/2019-ncov/faq.html) and we offer a few suggestions on what you can do. | ||
To protect everyone’s privacy, we keep all notifications confidential - that means we do not share information about who has symptoms, | ||
who has confirmed infection or who has been in contact with people who may be infected. We only use your contact information to notify | ||
you now of possible COVID exposure and will never use personal information for anything else. | ||
Because you may have been exposed to the COVID-19 virus, we encourage you to self-monitor for symptoms. Actions you can take now follow: | ||
- Wear a facial covering to prevent infection of others. People can spread COVID-19 even without having symptoms, and we all need to protect those around us. | ||
- Monitor yourself by checking your temperature twice daily and watching for new symptoms like: | ||
- Fever | ||
- Cough or shortness of breath. | ||
- Fatigue | ||
- Muscle or body aches | ||
- Headache | ||
- Loss of taste or smell | ||
- Sore throat | ||
- Congestion or runny nose | ||
- Nausea or vomiting | ||
- Diarrhea | ||
- Wash your hands frequently and avoid touching your face. | ||
- Disinfect areas that you touch. | ||
If you have symptoms: | ||
- check with your healthcare provider about the need for medical care or testing | ||
- self-quarantine until you know you are not infectious | ||
- maintain social distance from others (at least 6 feet) for 14 days or, until cleared by a medical professional. | ||
Please go to the Oasis website (http://1oasis.org/) to access COVID-19 information and, if you choose, you can report how you are feeling. | ||
You can learn more from the CDC (https://www.cdc.gov/coronavirus/2019-ncov/if-you-are-sick/quarantine.html?CDC_AA_refVal=https%3A%2F%2Fwww.cdc.gov%2Fcoronavirus%2F2019-ncov%2Fif-you-are-sick%2Fquarantine-isolation.html) about how to care for yourself if you’ve been exposed to COVID-19. | ||
""" | ||
|
||
EXPOSURE_NOTIFICATION_HTML_CONTENT = """ | ||
<html> | ||
<head></head> | ||
<body> | ||
<p>Hello. This is a notice from Oasis, a citizen-led global community working to stop the spread of COVID-19. | ||
Oasis community volunteers document their symptoms and COVID-19 test results on the Oasis platform. | ||
In addition, they can provide contact information of people whom they have been near and who may have been exposed to the virus. | ||
This notification is to let you know that <b>you may have been exposed</b> to the <a href='https://www.cdc.gov/coronavirus/2019-ncov/faq.html'>COVID-19 virus</a> and we offer a few suggestions on what you can do.</p> | ||
<p>To protect everyone’s privacy, we keep all notifications confidential - that means we do not share information about who has symptoms, | ||
who has confirmed infection or who has been in contact with people who may be infected. We only use your contact information to notify you now of possible COVID exposure and will never use personal information for anything else.</p> | ||
<p>Because <b>you may have been exposed</b> to the COVID-19 virus, we encourage you to self-monitor for symptoms. Actions you can take now follow:</p> | ||
<ul> | ||
<li>Wear a facial covering to prevent infection of others. People can spread COVID-19 even without having symptoms, and we all need to protect those around us.</li> | ||
<li>Monitor yourself by checking your temperature twice daily and watching for new symptoms like: | ||
<ul> | ||
<li>Fever</li> | ||
<li>Cough or shortness of breath.</li> | ||
<li>Fatigue</li> | ||
<li>Muscle or body aches</li> | ||
<li>Headache</li> | ||
<li>Loss of taste or smell</li> | ||
<li>Sore throat</li> | ||
<li>Congestion or runny nose</li> | ||
<li>Nausea or vomiting</li> | ||
<li>Diarrhea</li> | ||
</UL> | ||
</li> | ||
<li>Wash your hands frequently and avoid touching your face.</li> | ||
<li>Disinfect areas that you touch.</li> | ||
</ul> | ||
<p><b>If you have symptoms:</b></p> | ||
<ul> | ||
<li>check with your healthcare provider about the need for medical care or testing</li> | ||
<li>self-quarantine until you know you are not infectious</li> | ||
<li>maintain social distance from others (at least 6 feet) for 14 days or, until cleared by a medical professional.</li> | ||
</ul> | ||
<p>Please go to the <a href='http://1oasis.org/'>Oasis website</a> to access COVID-19 information and, if you choose, you can report how you are feeling. | ||
You can learn more from the <a href='https://www.cdc.gov/coronavirus/2019-ncov/if-you-are-sick/quarantine.html?CDC_AA_refVal=https%3A%2F%2Fwww.cdc.gov%2Fcoronavirus%2F2019-ncov%2Fif-you-are-sick%2Fquarantine-isolation.html'>CDC</a> about how to care for yourself if you’ve been exposed to COVID-19. </p> | ||
</body> | ||
</html> | ||
""" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
import os | ||
import smtplib | ||
from email.mime.multipart import MIMEMultipart | ||
from email.mime.text import MIMEText | ||
|
||
SENDER = os.environ.get("SMTP_FROM_ADDRESS", "") | ||
USERNAME_SMTP = os.environ.get("SMTP_USER", "") | ||
PASSWORD_SMTP = os.environ.get("SMTP_PASS", "") | ||
HOST = os.environ.get("SMTP_SERVER", "") | ||
PORT = os.environ.get("SMTP_PORT", "") | ||
|
||
|
||
def send(to: str, subject: str, body_text: str, body_html: str = None): | ||
|
||
# Create message container | ||
msg = MIMEMultipart("alternative") | ||
msg["From"] = SENDER | ||
msg["To"] = to | ||
msg["Subject"] = subject | ||
|
||
# Record the MIME types of both parts - text/plain and text/html. | ||
part1 = MIMEText(body_text, "plain") | ||
part2 = MIMEText(body_html, "html") | ||
|
||
# Attach parts into message container. | ||
# According to RFC 2046, the last part of a multipart message, in this case | ||
# the HTML message, is best and preferred. | ||
msg.attach(part1) | ||
msg.attach(part2) | ||
|
||
# Try to send the message. | ||
try: | ||
if os.environ.get("DEV", False): | ||
print(msg.as_string()) | ||
else: | ||
server = smtplib.SMTP(HOST, PORT) | ||
server.ehlo() | ||
server.starttls() | ||
# stmplib docs recommend calling ehlo() before & after starttls() | ||
server.ehlo() | ||
server.login(USERNAME_SMTP, PASSWORD_SMTP) | ||
server.sendmail(SENDER, to, msg.as_string()) | ||
server.close() | ||
# Display an error message if something goes wrong. | ||
except Exception as e: | ||
print("Error: ", e) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.