diff --git a/apimail/admin.py b/apimail/admin.py
index c59fd81630f95d8e00dfc2d4f7adc8456593c9b0..b0d30561c920ba670b854ea6c871bf337de093d0 100644
--- a/apimail/admin.py
+++ b/apimail/admin.py
@@ -6,7 +6,7 @@ from django.contrib import admin
 
 from .models import (
     EmailAccount, EmailAccountAccess,
-    ComposedMessage,
+    ComposedMessage, ComposedMessageAPIResponse,
     Event,
     StoredMessage, StoredMessageAttachment,
     UserTag)
@@ -24,8 +24,13 @@ class EmailAccountAdmin(admin.ModelAdmin):
 admin.site.register(EmailAccount, EmailAccountAdmin)
 
 
+class ComposedMessageAPIResponseInline(admin.StackedInline):
+    model = ComposedMessageAPIResponse
+    extra = 0
+    min_num = 0
+
 class ComposedMessageAdmin(admin.ModelAdmin):
-    pass
+    inlines = [ComposedMessageAPIResponseInline,]
 
 admin.site.register(ComposedMessage, ComposedMessageAdmin)
 
diff --git a/apimail/management/commands/mailgun_send_messages.py b/apimail/management/commands/mailgun_send_messages.py
new file mode 100644
index 0000000000000000000000000000000000000000..70eada7b2006908277ce7810ffff95323fe54f10
--- /dev/null
+++ b/apimail/management/commands/mailgun_send_messages.py
@@ -0,0 +1,44 @@
+__copyright__ = "Copyright © Stichting SciPost (SciPost Foundation)"
+__license__ = "AGPL v3"
+
+
+import requests
+
+from django.conf import settings
+from django.core.management import BaseCommand
+
+from ...models import ComposedMessage, ComposedMessageAPIResponse
+
+
+class Command(BaseCommand):
+
+    def handle(self, *args, **options):
+        emails_ready_to_send = ComposedMessage.objects.ready()
+
+        for msg in emails_ready_to_send:
+            data = {
+                'from': msg.from_account.email,
+                'to': msg.to_recipient,
+                'subject': msg.subject,
+                'text': msg.body_text,
+                'html': msg.body_html,
+            }
+            if msg.cc_recipients:
+                data['cc'] = msg.cc_recipients
+            if msg.bcc_recipients:
+                data['bcc'] = msg.bcc_recipients
+
+            response = requests.post(
+                "https://api.eu.mailgun.net/v3/%s/messages" % settings.MAILGUN_DOMAIN_NAME,
+                auth=("api", settings.MAILGUN_API_KEY),
+                data=data)
+
+            msgr = ComposedMessageAPIResponse(
+                message=msg,
+                status_code=response.status_code,
+                json=response.json())
+            msgr.save()
+
+            if response.status_code == 200:
+                ComposedMessage.objects.filter(uuid=msg.uuid
+                ).update(status=ComposedMessage.STATUS_SENT)
diff --git a/apimail/managers.py b/apimail/managers.py
index fc4ca3d9e3eb7daa9add817568ea0eb6e2f45cd3..2e6e02376afdd4c0d6e3dd6ce0e8915745cdd349 100644
--- a/apimail/managers.py
+++ b/apimail/managers.py
@@ -22,6 +22,9 @@ class ComposedMessageQuerySet(models.QuerySet):
     def filter_for_user(self, user):
         return self.filter(author=user)
 
+    def ready(self):
+        return self.filter(status='ready')
+
 
 class StoredMessageQuerySet(models.QuerySet):
     """
diff --git a/apimail/migrations/0013_composedmessageapiresponse.py b/apimail/migrations/0013_composedmessageapiresponse.py
new file mode 100644
index 0000000000000000000000000000000000000000..1538e74890c1db9cacce82cf137baeca250660f4
--- /dev/null
+++ b/apimail/migrations/0013_composedmessageapiresponse.py
@@ -0,0 +1,28 @@
+# Generated by Django 2.1.8 on 2020-01-31 08:01
+
+import django.contrib.postgres.fields.jsonb
+from django.db import migrations, models
+import django.db.models.deletion
+import django.utils.timezone
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('apimail', '0012_composedmessage'),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='ComposedMessageAPIResponse',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('datetime', models.DateTimeField(default=django.utils.timezone.now)),
+                ('response', django.contrib.postgres.fields.jsonb.JSONField(default=dict)),
+                ('message', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='api_responses', to='apimail.ComposedMessage')),
+            ],
+            options={
+                'ordering': ['-datetime'],
+            },
+        ),
+    ]
diff --git a/apimail/migrations/0014_auto_20200131_0956.py b/apimail/migrations/0014_auto_20200131_0956.py
new file mode 100644
index 0000000000000000000000000000000000000000..c99aef522eff9ea9c76fe319e5a4029d70edc103
--- /dev/null
+++ b/apimail/migrations/0014_auto_20200131_0956.py
@@ -0,0 +1,24 @@
+# Generated by Django 2.1.8 on 2020-01-31 08:56
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('apimail', '0013_composedmessageapiresponse'),
+    ]
+
+    operations = [
+        migrations.RenameField(
+            model_name='composedmessageapiresponse',
+            old_name='response',
+            new_name='json',
+        ),
+        migrations.AddField(
+            model_name='composedmessageapiresponse',
+            name='status_code',
+            field=models.PositiveSmallIntegerField(default=200),
+            preserve_default=False,
+        ),
+    ]
diff --git a/apimail/models/__init__.py b/apimail/models/__init__.py
index 78b5e8e2161c0ce676c326013f317ee1f9d32678..f211191ef619b76555163c6e55b2febf13842a3a 100644
--- a/apimail/models/__init__.py
+++ b/apimail/models/__init__.py
@@ -4,7 +4,7 @@ __license__ = "AGPL v3"
 
 from .account import EmailAccount, EmailAccountAccess
 
-from .composed_message import ComposedMessage
+from .composed_message import ComposedMessage, ComposedMessageAPIResponse
 
 from .event import Event
 
diff --git a/apimail/models/composed_message.py b/apimail/models/composed_message.py
index ef3fe8964727e52cbe4eeafde1e442aebe83294f..1d3a22ec6eb4bd8b6e87b1fd1c5c6a4b6c2584a0 100644
--- a/apimail/models/composed_message.py
+++ b/apimail/models/composed_message.py
@@ -5,7 +5,7 @@ __license__ = "AGPL v3"
 import uuid as uuid_lib
 
 from django.conf import settings
-from django.contrib.postgres.fields import ArrayField
+from django.contrib.postgres.fields import ArrayField, JSONField
 from django.db import models
 from django.utils import timezone
 
@@ -72,3 +72,19 @@ class ComposedMessage(models.Model):
             self.from_account.email,
             self.to_recipient,
             self.get_status_display())
+
+
+class ComposedMessageAPIResponse(models.Model):
+    """
+    Mailgun API response upon action on ComposedMessage.
+    """
+    message = models.ForeignKey(
+        'apimail.ComposedMessage',
+        on_delete=models.CASCADE,
+        related_name='api_responses')
+    datetime = models.DateTimeField(default=timezone.now)
+    status_code = models.PositiveSmallIntegerField()
+    json = JSONField(default=dict)
+
+    class Meta:
+        ordering = ['-datetime']