I'm very new to Javascript and working on mail, project 3 for CS50 web. I've been working on just sending the email initially, for about a week and I'm getting very discouraged. I can't seem to get the API to actually send the email. I keep getting internal server errors at the area in the code where I fetch.

I've watched the JS video including the API information, twice. I've scoured the instructions. Is there something specific you need to do, to get the API to work and actually send the email? It's to the point where I have started to copy and paste code from github, just to see if I can get anything to work but I either get errors, or nothing happens. If I go to the admin section, nothing is saved. I haven't touched any of the Django, urls, etc in the project at all.

Any help is so appreciated.

Example of something I tried:


    document.addEventListener('DOMContentLoaded', function() {

       // Use buttons to toggle between views
      document.querySelector('#inbox').addEventListener('click', () => load_mailbox('inbox'));
      document.querySelector('#sent').addEventListener('click', () => load_mailbox('sent'));
      document.querySelector('#archive').addEventListener('click', () => 
      document.querySelector('#compose').addEventListener('click', compose_email);
      document.querySelector('#compose-form').onsubmit = send_email;
      // By default, load the inbox

    function compose_email() {

      // Show compose view and hide other views
      document.querySelector('#emails-view').style.display = 'none';
      document.querySelector('#compose-view').style.display = 'block';
        document.querySelector('#single-email-view').style.display = 'none';
        document.querySelectorAll("button").forEach(button => button.classList.remove("selected"));

      // Clear out composition fields
      document.querySelector('#compose-recipients').value = '';
      document.querySelector('#compose-subject').value = '';
      document.querySelector('#compose-body').value = '';

    function load_mailbox(mailbox) {
      // Show the mailbox and hide other views
      document.querySelector('#emails-view').style.display = 'block';
      document.querySelector('#compose-view').style.display = 'none';
       document.querySelector('#single-email-view').style.display = 'none';
      document.querySelectorAll("button").forEach(button => 

      // Show the mailbox name
      document.querySelector('#emails-view').innerHTML = `<h3>${mailbox.charAt(0).toUpperCase() + mailbox.slice(1)}</h3>`;

      // Update the mailbox with the latest emails to show for this mailbox.
        .then(response => response.json())
        .then(emails => {

            const sections_to_show = [['sender', 5], ['subject', 3], ['timestamp', 4]];
            const artificial_first_email = {'sender': 'Sender', 'subject': 'Subject', 'timestamp': 'Date and time',
                'read': true};
            emails = [artificial_first_email, ...emails];
            emails.forEach(email => {
                const row_div_element = document.createElement('div');
                row_div_element.classList.add("row","email-line-box", email["read"] ? "read" : "unread");
                if (email === artificial_first_email) {row_div_element.id = 'titled-first-row';}
                    section => {
                        const section_name = section[0];
                        const section_size = section[1];
                        const div_section = document.createElement('div');
                        div_section.classList.add(`col-${section_size}`, `${section_name}-section`);
                        div_section.innerHTML = `<p>${email[section_name]}</p>`;

                if (email !== artificial_first_email) {
                    row_div_element.addEventListener('click', () => load_email(email["id"], mailbox));


          .catch(error => console.log(error)); // just in case!

    function send_email() {
      const recipients = document.querySelector('#compose-recipients').value;
      const subject = document.querySelector('#compose-subject').value;
      const body = document.querySelector('#compose-body').value;
      fetch('/emails', {
        method: 'POST',
        body: JSON.stringify({
          recipients: recipients,
          subject: subject,
          body: body
        .then(response => response.json())
         .then(result => {
           if ("message" in result) {
               // The email was sent successfully!

           if ("error" in result) {
                // There was an error in sending the email
               // Display the error next to the "To:"
                 document.querySelector('#to-text-error-message').innerHTML = result['error']

            console.log("message" in result);
            console.log("error" in result);
            .catch(error => {
      return false;
  • Did you check the database using admin?
    – Vsjain
    Feb 17, 2021 at 14:20
  • @Vsjain yes, nothing is there. Nothing gets saved Feb 18, 2021 at 1:15

2 Answers 2


I am in the same position... nothing works... I think I cannot reach the API, because I sent the form empty and non error come back...

Did you manage to soved this? if yes... how?

Thanks in advance...

  • I was able to get it to work and send the email. If nothing is saving in your form, then you probably have another problem in your code though, not just the API. I found a bug in the distribution code in models.py too - check to see if you have this under class Email and def serialize(self): "timestamp": self.timestamp.strftime("%b %d %Y, %I:%M %p"), The distribution code saved differently for me so I had to change it to this. If you have a link to your code here on stack exchange, I can try to help. Apr 6, 2021 at 1:52
  • This does not provide an answer to the question. To critique or request clarification from an author, leave a comment below their post. - From Review
    – MARS
    May 1, 2021 at 23:01
  • 1
    This does not really answer the question. If you have a different question, you can ask it by clicking Ask Question. To get notified when this question gets new answers, you can follow this question. Once you have enough reputation, you can also add a bounty to draw more attention to this question. - From Review
    – Cliff B
    Jun 16, 2021 at 22:33

I don't really understand what the reason for this is, it is as if the browser retains some cached data so pressing shift + f5 will reload all the files on the page and solve that problem

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .