A single-page-app email client that makes API calls to send and receive emails with front-end similar to Gmail.
After cloning the repo you need to create a Virtual environment and activate it.
First install virtualenv package
pip install virtualenv
Open cli in the folder of the cloned repo and then create env
virtualenv env
To activate the env (For windows, For other OS you can easily google)
env\Scripts\activate
Install the dependencies from the requirements.txt file
cd mail
pip install -r requirements.txt
Start the django server
python manage.py runserver
Now you can access the project at http://127.0.0.1:8000
- Send Mail - User is able to send mails passing in values for recipients, subject, and body.
- Mailbox - The appropriate mailbox is loaded on visiting the Inbox, Sent, Archive, Starred or Trash mailbox.
- View Email - When a user clicks on an email, the user is taken to a view where they see the content of that email.
- Archive and Unarchive - Users are able to archive and unarchive emails.
- Reply - Users are able to reply to emails received and even forward them.
- Search - Users can search emails based on any keyword present in their email description or usernames.
- History Api - Enables page navigation and routing in pure vanilla JavaScript through powerful set of methods for SPAs.
- CkEditor - Povides user with a WYSIWYG to write custom with styling and images emails.
- Mobile responsive - UI not only adapts to the screen size but changes accordingly to match with actual Gmail UI.
- Live Site URL: Deployed on Render
- Django - High-level Python web framework
- CKEditor - JavaScript rich text editor (WYSIWYG)
- Bootstrap
- Javascript
- Semantic HTML5 markup
- CSS custom properties
- Flexbox
- Media queries
I am using this section to recap over some of my major learnings while working through this project. I feel writing these out and providing code samples of areas I want to highlight is a great way to reinforce my own knowledge.
-
Q Objects To execute more complex queries with django ORM (for example, queries with OR statements) you need to use Q objects. I used them at multiple places in my views and they make up my simple search feature work.
# My simple search query # Here Q with | works similar to LIKE OR query of SQL #Note: __contains __(case-sensitive) and icontains (case-insensitive) results = Email.objects.filter(user=request.user)\ .filter(Q(sender__email__icontains=query) | Q(sender__first_name__icontains=query) | Q(sender__last_name__icontains=query) | Q(subject__icontains=query) | Q(body__icontains=query)).distinct()
-
JsonResponse JsonResponse is an HttpResponse subclass that helps to create a JSON-encoded response. Based on my usecase it enabled me to make a simple API with a serializer inside my model that returns the data in required JSON format.
# views.py def mailbox(request, mailbox): #skipped some code here return JsonResponse([email.serialize() for email in emails], safe=False) #models.py class Email(models.Model): #skipped some code here def serialize(self): return { "id": self.id, "username": self.sender.first_name +" "+self.sender.last_name, "sender": self.sender.email, "recipients": [user.first_name +" "+user.last_name for user in self.recipients.all()], "subject": self.subject, "body": self.body, "timestamp": self.timestamp.strftime("%b %d-%Y-%H:%M %p" ), "read": self.read, "archived": self.archived, "starred": self.starred, "deleted": self.deleted, }
-
History Api Single page applications do not re-render pages rather they make changes to the page asynchronously. While this feature looks appealing to the user the state of the website is no longer saved by the browser as it is done with multi-page websites. So inorder to make the back and forward history buttons of the browser the history API is used.
To use the browser’s history functionality, you begin by telling the browser to remember your initial state. This requires the replaceState method
// Initial State // To use the browser’s history functionality, // you begin by telling the browser to remember your initial state. history.replaceState({ mailbox: "inbox" }, "Default state", "#inbox"); //Behind the scenes, The History Api uses a Stack data structure. //Pushstate pushes states to the stack history.pushState({ mailbox: mailbox }, "", `./#${mailbox}`); //Popstate pop states out of the stack window.addEventListener("popstate", (e) => { load_mailbox(e.state.mailbox); //Popstate }
I am using this section to outline areas that I want to continue focusing on in future for this project.
Tasks To Do
- Loading Spinners
- ML model to detect spam mails
- Pagination + Infinite Scroll
- Code Refactoring
- My teacher and CSS Expert kevin powell by whom I learned responsive design reviewed the design of my gmail clone and he loved it.
- Link to the video
- Q object docs - This is the django doc i reffered for understanding Q objects.
- History Api - This is an amazing article which helped me finally understand History Api. I'd recommend it to anyone still learning this concept.
- Profile - Hussain Shaikh
- Twitter - @HussainSk2001
- CS50 and Brian Yu - I am absolutely thankfull to them as they enabled me to learn such amazing concepts free of cost and gave me an headstart in web development. I would recommend it anybody who wants to become a web dev.
- Kevin Powell - His course conquering responsive layouts gave me the weapons to tackle one of the toughest things in web development, CSS!!.