Coder Social home page Coder Social logo

ascoderu / lokole Goto Github PK

View Code? Open in Web Editor NEW
45.0 14.0 12.0 5.87 MB

Source code for the Lokole project. Lokole enables communities in the Congo DRC to pool resources to access efficient communication via email at an affordable price.

Home Page: https://ascoderu.ca

License: Apache License 2.0

Python 75.23% Makefile 1.25% Shell 7.33% Dockerfile 1.69% Smarty 0.52% JavaScript 6.34% HTML 6.96% CSS 0.13% Mustache 0.55%
python3 connexion sendgrid kubernetes helm docker celery libcloud reactjs antd

lokole's Introduction

Lokole

What's this?

This repository contains the source code for the Lokole project by the Canadian-Congolese non-profit Ascoderu. The Lokole project consists of two main parts: an email client and an email server.

The Lokole email client is a simple application that offers functionality like:

  1. Self-service creation of user accounts
  2. Read emails sent to the account
  3. Write emails including rich formatting
  4. Send attachments

All emails are stored in a local SQLite database. Once per day, the emails that were written during the past 24 hours get exported from the database, stored in a JSON file, compressed and uploaded to a location on Azure Blob Storage. The Lokole Server picks up these JSON files, manages the actual mailboxes for the users on the Lokole and sends new emails back to the Lokole by using the same compressed file exchange format.

The Lokole email application is intended to run on low-spec Raspberry Pi 3 hardware (or similar). Read the "Production setup" section below for further information on how to set up the client devices.

The Lokole email server has two main responsibilities:

  1. Receive emails from the internet that are addressed to Lokole users and forward them to the appropriate Lokole device.
  2. Send new emails created by Lokole users to the rest of the internet.

Why is this useful?

Email is at the core of our modern life, letting us keep in touch with friends and family, connecting us to our businesses partners and fostering innovation through exchange of information.

However, in many parts of the developing world, email access is not very wide-spread, usually because bandwidth costs are prohibitively high compared to local purchasing power. For example, in the Democratic Republic of the Congo (DRC) only 3% of the population have access to emails which leaves 75 million people unconnected.

The Lokole is a project by the Canadian-Congolese non-profit Ascoderu that aims to address this problem by tackling it from three perspectives:

  1. The Lokole is an email client that only uses bandwidth on a schedule. This reduces the cost of service as bandwidth can now be purchased when the cost is lowest. For example, in the DRC, $1 purchases only 65 MB of data during peak hours. At night, however, the same amount of money buys 1 GB of data.
  2. The Lokole uses an efficient data exchange format plus compression so that it uses minimal amounts of bandwidth, reducing the cost of service. All expensive operations (e.g. creating and sending of emails with headers, managing mailboxes, etc.) are performed on a server in a country where bandwidth is cheap.
  3. The Lokole only uses bandwidth in batches. This means that the cost of service can be spread over many people and higher savings from increased compression ratios can be achieved. For example, individually purchasing bandwidth for $1 to check emails is economically un-viable for most people in the DRC. However, the same $1 can buy enough bandwidth to provide email for hundreds of people via the Lokole. Spreading the cost in this way makes email access sustainable for local communities.

System overview

Technologies

Below is a list of some of the key technologies used in the Lokole project:

  • Connexion is the web framework for the Lokole email server API.
  • Flask is the web framework for the Lokole email client application.
  • Dnsmasq and hostapd are used to set up a WiFi access point on the Lokole device via which the Lokole email client application is accessed.
  • WvDial is used to access the internet on the Lokole device to synchronize emails with the Lokole email server.
  • Celery is used to run background workers of the Lokole email server in Azure ServiceBus (production) or RabbitMQ (development). Celery is also used to run background workers and scheduled tasks on the Lokole email client application in SQLAlchemy.
  • Libcloud is used to store emails in Azure Storage (production) or Azurite (development).
  • Sendgrid Inbound Parse is used to receive emails from email providers and forward them to the Lokole email server. Sendgrid Web API v3 is used to deliver emails from the Lokole email server to email providers. The MX records for Sendgrid are automatically generated via Cloudflare API v4.
  • Github API v4 is used to authenticate interactive calls to the Lokole email server API such as registering new clients or managing existing clients. Authorization is managed by Github team memberships on the Ascoderu organization. Management operations are exposed via the Lokole status page which is implemented in React with Ant Design.
  • Github Actions are used to verify pull requests and deploy updates to production.

The diagram below shows the technologies in the context of the system as well as their interactions:

Overview of technologies and interactions in the Lokole system

Interactions

The key data flows and client/server interactions of the system are documented in the diagrams below.

Overview of the Lokole client registration flow Overview of the Lokole client email upload flow Overview of the Lokole client email download flow

Data exchange format

In order to communicate between the Lokole cloud server and the Lokole email application, a protocol based on gzipped jsonl files uploaded to Azure Blob Storage is used. The files contains a JSON object per line. Each JSON object describes an email, using the following schema:

{
  "sent_at": "yyyy-mm-dd HH:MM",
  "to": ["email"],
  "cc": ["email"],
  "bcc": ["email"],
  "from": "email",
  "subject": "string",
  "body": "html",
  "attachments": [{"filename": "string", "content": "base64", "cid": "string"}]
}

Development setup

First, install the system dependencies:

Second, get the source code.

git clone [email protected]:ascoderu/lokole.git
cd lokole

Third, build the project images. This will also verify your checkout by running the unit tests and other CI steps such as linting:

make build

You can now run the application stack:

make start logs

Finding your way around the project

There are OpenAPI specifications that document the functionality of the application and provide references to the entry points into the code (look for the yaml files in the swagger directory). The various APIs can also be easily called via the testing console that is available by adding /ui to the end of the API's URL. Sample workflows are shown in the integration tests folder and can be run via:

# run the services, wait for them to start
make build start

# in another terminal, run the integration tests
# the integration tests also serve the purpose of
# seeding the system with some test data
# you can access the email service at http://localhost:8080
# you can access the email client at http://localhost:5000
# you can access the status page at http://localhost:3000
make integration-tests test-emails

# finally, tear down the services
make stop

The state of the system can be inspected via:

# run the development tools and then
# view storage state at http://localhost:10001
# view database state at http://localhost:8882
# view queue state at http://localhost:5555
make start-devtools

Note that by default the application is run in a fully local mode, without leveraging any cloud services. For most development purposes this is fine but if you wish to set up the full end-to-end stack that leverages the same services as we use in production, keep on reading.

Integration setup

The project uses Sendgrid, so to emulate a full production environment, follow these Sendgrid setup instructions to create a free account, authenticate your domain, and create an API key with at least Inbound Parse and Mail Send permissions.

The project uses Cloudflare to automate DNS management whenever new Lokole clients are set up. Create an account, set your domain to be managed by Cloudflare and look up the Cloudflare Global API Key.

The project also makes use of a number of Azure services such as Blobs, Tables, Queues, Application Insights, and so forth. To set up all the required cloud resources programmatically, you'll need to create a service principal by following these Service Principal instructions. After you created the service principal, you can run the Docker setup script to initialize the required cloud resources.

cat > ${PWD}/secrets/sendgrid.env << EOM
LOKOLE_SENDGRID_KEY={the sendgrid key you created earlier}
EOM

cat > ${PWD}/secrets/cloudflare.env << EOM
LOKOLE_CLOUDFLARE_USER={your cloudflare user account email address}
LOKOLE_CLOUDFLARE_KEY={your cloudflare global api key}
EOM

cat > ${PWD}/secrets/users.env << EOM
OPWEN_SESSION_KEY={some secret for user session management}
LOKOLE_REGISTRATION_USERNAME={some username for the registration endpoint}
LOKOLE_REGISTRATION_PASSWORD={some password for the registration endpoint}
EOM

docker-compose -f ./docker-compose.yml -f ./docker/docker-compose.setup.yml build setup
docker-compose -f ./docker-compose.yml -f ./docker/docker-compose.setup.yml run --rm \
  -e SP_APPID={appId field of your service principal} \
  -e SP_PASSWORD={password field of your service principal} \
  -e SP_TENANT={tenant field of your service principal} \
  -e SUBSCRIPTION_ID={subscription id of your service principal} \
  -e LOCATION={an azure location like eastus} \
  -e RESOURCE_GROUP_NAME={the name of the resource group to create or reuse} \
  -v ${PWD}/secrets:/secrets \
  setup ./setup.sh

The secrets to access the Azure resources created by the setup script will be stored in files in the secrets directory. Other parts of the project's tooling (e.g. docker-compose) depend on these files so make sure to not delete them.

Production deployment

To set up a production-ready deployment of the system, follow the development setup scripts described above, but additionally also pass the following environment variables to the Docker setup script:

  • DEPLOY_COMPUTE: Must be set to k8s to toggle the Kubernetes deployment mode.
  • KUBERNETES_RESOURCE_GROUP_NAME: The resource group into which to provision the Azure Kubernetes Service cluster.
  • KUBERNETES_NODE_COUNT: The number of VMs to provision into the cluster. This should be an odd number and can be dynamically changed later via the Azure CLI.
  • KUBERNETES_NODE_SKU: The type of VMs to provision into the cluster. This should be one of the supported Linux VM sizes.

The script will then provision a cluster in Azure Kubernetes Service and install the project via Helm. The secrets to connect to the provisioned cluster will be stored in the secrets directory.

As an alternative to the Kubnernets deployment, a Virtual Machine may also be provisioned to run the services by passing the following environment variables to the Docker setup script:

  • DEPLOY_COMPUTE: Must be set to vm to toggle the Virtual Machine deployment mode.
  • VM_RESOURCE_GROUP_NAME: The resource group into which to provision the Azure Virtual Machine.
  • VM_SKU: The type of VMs to provision into the cluster. This should be one of the supported Linux VM sizes.

There is a script to set up a new Lokole email client. The script will install the email app in this repository as well as standard infrastructure like nginx and gunicorn. The script will also make ready peripherals like the USB modem used for data exchange, and set up any required background jobs such as the email synchronization cron job.

The setup script assumes that you have already set up:

  • 3 Azure Storage Accounts, general purpose: for the cloudserver to manage its queues, tables and blobs.
  • 1 Azure Storage Account, blob storage: for the cloudserver and email app to exchange email packages.
  • 1 Application Insights account: to collect logs from the cloudserver and monitor its operations.
  • 1 SendGrid account: to send and receive emails in the cloudserver.

The setup script is tested with hardware:

The setup script is also tested with USB modems:

The setup script installs the latest version of the email app published to PyPI. New versions get automatically published to PyPI (via Travis) whenever a new release is created on Github.

You can run the script on your client device like so:

curl -fsO https://raw.githubusercontent.com/ascoderu/lokole/master/install.py && \
sudo python3 install.py <client-name> <sim-type> <sync-schedule> <registration-credentials>

Adding a new language

To translate Lokole to a new language, install Python, Babel and a translation editor such as poedit. Then follow the steps below.

# set this to the ISO 639-1 language code for which you are adding the translation
export language=ln

# generate the translation file
pybabel init -i babel.pot -d opwen_email_client/webapp/translations -l "${language}"

# fill-in the translation file
poedit "opwen_email_client/webapp/translations/${language}/LC_MESSAGES/messages.po"

# finalize the translation file
pybabel compile -d opwen_email_client/webapp/translations

lokole's People

Contributors

adamsclafani avatar c-w avatar dependabot[bot] avatar initmahesh avatar laura-barluzzi avatar mabuelhagag avatar mransaw avatar mtotowamkwe avatar njengasaruni avatar pyup-bot avatar sbathgate avatar tezzytezzy avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

lokole's Issues

Make webapp setup not require ssh

What's this?

Currently to set up a new Lokole device, the user needs to:

  1. Burn an operating system to an SD card
  2. Mount the SD card in the Lokole device
  3. Connect the device to a router via Ethernet
  4. SSH into the device
  5. Download and run the setup script

This is a fairly technical process so it takes a bit of knowledge to setup a new device. It would be great if we could remove the SSH step from this process, e.g. by creating a custom OS build for Lokole.

Imported from https://github.com/ascoderu/opwen-setup/issues/4

Date and time

All the Lokole emails listing in the INBOX and SENT have the same date and time on the right columns. This date and time are current.

Search not working for user addresses

I tried to search the exact user_name in some email addresses I have in my sent and inbox emails. For example, I received an email from "clemens@..." and I searched for "clemens".
The screenshot shows that no results were provided for this type of search (the search string "clemens" was where the start is now, but it was automatically deleted after clicking "search"). However, the research on subjects and email contents did work just fine.

Selecting email contents based on people is very common and useful, I'd include email addresses into the search.

no_results_for_clemens

Printing emails option

There is no PRINT option on the Lokole app, But I can print from windows program

(Split out from ascoderu/opwen-webapp#19)

Forget password

The user cannot reinstate his/her password when forgotten

Resize inlined images

Following up on #3

We should resize the images that we inline in order to protect against people linking to super huge images and having the Lokole client consume too much bandwidth. We can just chose one reasonable dimension (e.g. 200px width) and then scale images to fit into that.

The image transformations can be done with the Pillow package (article).

Lots of extra data in email body

Sample content:

{
    "body":  "<div dir=3D\"ltr\">Hi Clemens,<div><br></div><div>Received 13 copies of this =\nsame email.</div><div><br></div><div>Yours,</div><div>Nzola</div></div><div=\n class=3D\"gmail_extra\"><br><div class=3D\"gmail_quote\">On Wed, Nov 23, 2016 =\nat 7:00 PM,  <span dir=3D\"ltr\">&lt;<a href=3D\"mailto:[email protected]=\nderu.ca\" target=3D\"_blank\">[email protected]</a>&gt;</span> wro=\nte:<br><blockquote class=3D\"gmail_quote\" style=3D\"margin:0 0 0 .8ex;border-=\nleft:1px #ccc solid;padding-left:1ex\">Sent via the <b>cloud</b>.<br><br><im=\ng src=3D\"https://u3660395.ct.sendgrid.net/wf/open?upn=3DfQYRXxfb11-2FQA-2BU=\nkcGlhhVGJttejnJ-2FZ0OYSn0mSCqdWiuvTyVKc4UKprYSnAHF9RFwStHGkiUaHoiD0o0yx-2Fz=\nxrdTb9bCoS6MES-2BL9cDzvtgVHEmB-2BrVyK5UBzvjj0TgIGv5dBhjaLbD3opMz0vxaoFZHy-2=\nFC75isVgDlGIgfSG4-2BIV6BI21juvKWoOJxYrYnWDwkNDycd4IUXV6P7b-2Fmc52hQxTnQavq5=\nVccN7y4z0-3D\" alt=3D\"\" width=3D\"1\" height=3D\"1\" border=3D\"0\" style=3D\"heigh=\nt:1px!important;width:1px!important;border-width:0!important;margin-top:0!i=\nmportant;margin-bottom:0!important;margin-right:0!important;margin-left:0!i=\nmportant;padding-top:0!important;padding-bottom:0!important;padding-right:0=\n!important;padding-left:0!important\">\n</blockquote></div><br></div>\n"
}

We could pre-process the html and strip out anything that the client won't render anyways.

Web address re-direction

To redirect any web address type on address bar to ascoderu.ca.
When one connect to the Lokole network, open the browser, has to type ascoderu.ca to access ascoderu email system. Can you implement any web address redirect clients to ascoderu.
This will have to benefits
1 - the user don't have to remember ascoderu.ca
2 - Ascoderu publicity to a pass by; I carry Lokole powered up with battery in my bag in the bus everyday. I know many smart phone users on the bus they see ascoderu network. If these people can access at least the front page, they would be interested to read and maybe donate. This may happen in DRC, too.

Portable Lokole emails

It is convenient to have Lokole local users to be able to access their emails anywhere around the world where there is Internet. (ex Internet Cafe)

Sub-tasks for this issue:

Carrier return to inbox

When one composes new email and click send. It says ; email is sent, but the mail sent still show on the front page as if it is not sent.
Can the front page returns to INBOX after one click the send?

Create template for services-via-email

One value-add of enabling email access in rural communities is the ability to provide services via email such as access to information (Wikipedia, Project Gutenberg, medical database, etc.), marketplaces (buy/sell), education (courses), etc.

The general idea is to have a semi-structured email template that can be sent to a particular inbox that then gets parsed, the information fetched and returned to the sender via a reply-email.

This project is to prove out this concept by implementing a particular service via email (e.g. Project Gutenberg via the gutenberg library) and build a template that future work can leverage to quickly build new services via email integrations.

Generalized service-via-email architecture diagram

Make compression smarter

What's this?

One of the main value-adds of the Ascoderu email client is that it makes email access affordable for users in sub-Saharan Africa by reducing the bandwidth costs associated with sending and receiving emails.

One way in which we reduce bandwidth costs is by never sending/receiving individual emails but instead sending/receiving batches of emails and adding compression on top of that. The larger the batches, the more bandwidth we save thanks to compression.

Right now, the compression is fairly naive: we just synchronize emails between the client and the server by exchanging gizpped jsonl files. This is a lot more efficient than exchanging emails as we don't include all the verbose MIME headers, but I'm sure that this can be improved: json is redundant after all and gzip is not a state-of-the art compression technique.

The aim of this task is to research and implement alternative data exchange protocols and compression techniques that will reduce our bandwidth requirements.

Getting started

The email sync looks like this:

image

The server-side piece is in storage.py in the opwen-cloudserver repository. The client-side piece is in sync.py in the opwen-webapp repository.

We want to minimize the amount of bandwidth used on the second and third steps in the diagram above, e.g. by using a file format with less overhead than jsonl and/or by using a better compression algorithm than gzip. Note that the compression will have to run on the Lokole client which is low-spec hardware (OrangePi or RaspberryPi).

Add support for email aliases

From @nzola:

I would like to suggest alias address option.

In case a person has already an email address such as Yahoo or Gmail that works in the big city and he/she has to travel to Basankusu for a particular project and stay there for a couple of weeks and he/she wants his/her emails be also copied to Lokole Basankusu or vice versa.

Fix SendGrid error

Traceback (most recent call last):
  File "/app/opwen_email_server/services/sendgrid.py", line 51, in _send_email
    response = self._client.client.mail.send.post(request_body=request)
  File "/usr/lib/python3.6/site-packages/python_http_client/client.py", line 227, in http_request
    return Response(self._make_request(opener, request))
  File "/usr/lib/python3.6/site-packages/python_http_client/client.py", line 157, in _make_request
    return opener.open(request)
  File "/usr/lib/python3.6/urllib/request.py", line 526, in open
    response = self._open(req, data)
  File "/usr/lib/python3.6/urllib/request.py", line 544, in _open
    '_open', req)
  File "/usr/lib/python3.6/urllib/request.py", line 504, in _call_chain
    result = func(*args)
  File "/usr/lib/python3.6/urllib/request.py", line 1361, in https_open
    context=self._context, check_hostname=self._check_hostname)
  File "/usr/lib/python3.6/urllib/request.py", line 1320, in do_open
    raise URLError(err)
urllib.error.URLError: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:749)>

Unable to format text on mobile

On mobile devices, the keyboard's cut/copy/paste dialog overlaps our formatting controls (see screenshot below).

We should move the formatting controls to prevent this. The email creation page is rendered by email_new.html and the WYSIWYG editor is initialized in email_new.js.

Integrate with Internet-in-a-Box

The Internet-in-a-Box project (Website, Github) is interested in onboarding Lokole as a local-only email service.

To make this integration happen, we'll need to build out a few things:

  • Create an Ansible playbook to deploy Lokole (currently we deploy via bash scripts).
  • Wrap Lokole in a systemd service for management (currently we use supervisord).
  • Enable Lokole to use a MySQL database (currently we use SQLite).

Azure Table Batches may only contain 100 operations

Error in the logs:

    raise AzureBatchValidationError(_ERROR_TOO_MANY_ENTITIES_IN_BATCH)
azure.storage.table.models.AzureBatchValidationError: Batches may only contain 100 operations
2017-05-24 03:34:18,125 ERROR   500 GET /api/email/lokole/__client_id__ (127.0.0.1) 11824.64ms

CC and BC

Lokole email system does not have any CC and BC on the address option

Add support for African SIM cards

Currently, the setup script for the Lokole device only works with a single SIM card (the Hologram global SIM). We need to add support for local African SIM cards so that we can make use of the best prices for bandwidth in each region where we'll deploy the Lokole devices.

We're using the wvdial tool to connect the SIM cards to the network via the USB modems, so this task involves researching the required dialer commands for each SIM card in our target countries (DRC, Uganda, Tanzania, etc.), testing them and adding them to the setup-webapp.sh script.

Starting point is the implementation of the Hologram global SIM's wvdial.conf entry:

[Dialer Defaults]
Init1 = ATZ
Init2 = ATQ0
Init3 = AT+CGDCONT=1,"IP","apn.konekt.io"
Phone = *99***1#
Stupid Mode = 1
Username = { }
Password = { }
Modem Type = Analog Modem
Modem = /dev/ttyUSB0
IDSN = 0

I'm not sure if this will work out of the box for the other SIM cards, but it should be okay as a starting point to be adapted. You can use the existing internet-connect script to test your wvdial configuration. In essence this script does two things: first use usb_modeswitch to ensure that the USB modem is ready to connect to the internet and then use wvdial to create the connection. I'd recommend to use the MS2131i USB modem for this task so that you can skip the first step. In essence, connecting to the internet via a modem with a given wvdial configuration then is as simple as:

sudo wvdial --config /path/to/your/wvdial/config/file

What you'll need for this task:

  • USB modem (I can provide a MS2131i which works very well with Linux devices)
  • African SIM cards (I can provide these)

Subtasks:

  • Vodacom Tanzania
  • Tigo Tanzania
  • AirTel Ghana
  • ??? DRC (pending SIM card)
  • ??? Uganda (pending SIM card)

Imported from https://github.com/ascoderu/opwen-setup/issues/8

Overview of the end-to-end USB/dialup process:

image

New incoming mail position

As per now, all the new emails come at the bottom of the last page.
Can this be modified to position new incoming emails on top of the first page

Each email gets sent 4 times

On the production machine, we're using 4 gunicorn workers. This leads to the email sending job being scheduled and executed 4 times. This is a known limitation of the task scheduling library we're using (see apscheduler-160).

Possible workarounds:

  • Only run with 1 gunicorn worker in production. This shouldn't be a big issue from a performance point of view as the only load the worker is taking is receiving, parsing and storing emails via the sendgrid parse webhook.
  • Add a check against a global state before executing the scheduled jobs. This has the potential for race-conditions and may get messy code-wise.
  • Initialize the scheduled jobs outside of the webapp. This would be quite a bit of refactoring.

Create a tropicalized case

What's this?

We'll be deploying the Lokole device hardwares in tropical climates. As such, we should enclose the hardware and peripherals (USB modem, battery) in a case that protects the device against dust, high temperatures, moisture, etc.

The quality and performance of the case will directly influence the longevity of the Lokole devices. As such, the better job we do here, the less our users will have to spend on replacing parts of the hardware, saving money for the rural African communities.

Getting started

We have two hardware models that we support so we'll have to design two cases (focus on the OrangePi first as it's the cheaper hardware so we'll deploy more of these):

OrangePi Zero

Raspberry Pi 3

Additionally, the case will have to enclose an optional battery and a required USB modem like Huawei E3131.

Imported from https://github.com/ascoderu/opwen-setup/issues/6

Improve UI

Sudheesh is a researcher who has a lot of experience in frontend for developing countries. This issue is to track any improvement ideas he has for the Lokole app.

@nzola and @laura-barluzzi may be interested in this too.

Add retry to email sync script

@nzola said:

Cell Lokole connects most of the time, but sometimes skips the connection and connects in the next round.

This is likely because of intermittent connectivity issues dialing up with the USB modem. We can add a retry wrapping the sync script to avoid this.

The sync script is generated by setup-lokole.sh when a new device is being provisioned. There's also a simpler version of this script that gets generated in setup-lokole-docker.sh. So both places would have to be updated to retry the sync a few times.

Add ability for admins to suspend accounts

From @nzola:

Barb, who is planning to deploy Lokole in Uganda suggested to give the localadmin of lokole some power allow or block users in case of system abuse.
They wanted a admin special logging to control their particular Lokole network for sustainable revenue. This way if the user does not pay, he cannot logging, like school network admin or Internet café.

Fix DataCollectionAgent.DiskSpaceAvailable warning on ServiceFabric

Warning message:

Unhealthy event: SourceId='FabricDCA', Property='DataCollectionAgent.DiskSpaceAvailable',
HealthState='Warning', ConsiderWarningAsError=false. The Data Collection Agent (DCA)
does not have enough disk space to operate. Diagnostics information will be left uncollected
if this continues to happen.

Enable attachment sharing

What's this?

If the same attachment is sent to N recipients on the same Lokole device, the attachment should only be transferred once between the server and client. Ideally, the implementation of this task will not change the jsonl data exchange format between the clients and server so that we can still process all emails in a streaming fashion instead of having to read all of them into memory as the latter may easily crash on the memory constrained Lokole hardware. One possible way to implement this feature is to add an id field to the attachment object that gets sent between the client and server and only include the content once per id. When deserializing the emails, the client can then re-use the same attachment for multiple recipients.

This will make use-cases like classroom-via-email and remote-teacher more efficient as the same lecture content is sent to multiple students in the same village serviced by Lokole. See also #5 for more context on the benefits of reducing bandwidth usage in the Lokole project and for pointers on how to get started with modifying the data sync and compression code in the client and server.

Restructure test_config.py

The test should only look at Azure-related constants (e.g. queue/table/container names) not at access keys, etc.

Deleting emails leaves orphaned entries in the emailattachments table

Repro steps:

  1. Create two accounts: userA and userB.
  2. Send an email with attachment from userA to userB.
  3. Inspect the DB echo 'SELECT id FROM email;' | sqlite3 /tmp/email.store and note the email ids.
  4. Inspect the DB echo 'SELECT id FROM attachment;' | sqlite3 /tmp/email.store and note the attachment ids.
  5. Log in as userB and delete the email in the UI.
  6. Inspect the DB echo 'SELECT email_id, attachment_id from emailattachment;' | sqlite3 /tmp/email.store and observe that:
    a) The attachment was deleted.
    b) The email was deleted.
    c) However, a row for the deleted email and its attachment remains in the association table.

Multiple emails

Sending to multiple emails either on TO, CC or BCC windows does not work.

Add support for rendering of classroom-emails

Part of the Connect.Ed integration.

Background on handling actions

You'll need the ability to perform actions from your classes emails, e.g. to reply from a student to the teacher with certain answers to a quiz.

We already have some functionality to handle a similar use-case in Ascoderu (email reply/reply-all/forward) which we can re-use.

Here is how forward is currently implemented in Ascoderu. There is a "forward" button on every email. When this button is clicked, we execute a GET to /email/new?action=forward?uid=${replied_email_id}. Based on the action, we then pre-populate a new email with certain data, e.g. the body of the forwarded email.

Handling an action can be simple (e.g. just pre-populating the subject in the case of a reply action) or more complex (e.g. pre-populating the body of the email with the content of a forwarded email according to a template). The information that's available at the time when the action gets processed is the action type and the full context of the email that triggered the action.

We can re-use this mechanism for courses for pre-populating emails with quiz answers and similar. The user then only has to hit send and they're done. In order to make the parsing of the emails that contain answers more reliable, you could use a custom reply email template to include hidden guids for the different answer types.

Click event doesn't bring to home page

When I hover on Ascoderu on the navigation bar, the cursor changes to "clickable" mode but when I click on it it remains on the current page instead of going to the home page.

However, the url change and a "#" is added at the end. See below:

after_clicking

Optimize storage usage

Some redundant data is stored in Blob that can be deleted after it was processed, e.g. anything in the containers compresedpackages and sendgridinboundemails.

Add support for inline images

Inline images don't get rendered on the clients.

image

The problem is that the inline images reference URLs but the clients don't have an internet connection.

The fix is to fetch the images at receiving time and inline them using base64. A good place where to implement this is likely in the background job that processes incoming emails (store_inbound_emails.py) where we can fetch any inline linked images and convert them to base64 before inserting the email into our database.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.