diff --git a/hook/fetch-meetings.py b/hook/fetch-meetings.py
index 5818b0937b62dac6ca70d2bca17eb1c1a1d8defa..873000a8818d679b856491f1037bc3e29723a9a8 100755
--- a/hook/fetch-meetings.py
+++ b/hook/fetch-meetings.py
@@ -20,6 +20,11 @@ db_conn = psycopg2.connect(dbname=config['db']['name'], user=config['db']['user'
 db = db_conn.cursor(cursor_factory=psycopg2.extras.NamedTupleCursor)
 
 
+def die(msg):
+    print(msg, file=sys.stderr)
+    sys.exit(1)
+
+
 def parse_time(iso_time):
     return dateutil.parser.isoparse(iso_time)
 
@@ -140,23 +145,32 @@ def fetch_all():
 
 
 def fetch_single(user_email, meeting_id):
-    db.execute("SELECT * FROM zoom_users WHERE email=%s", (user_email,))
-    user_row = db.fetchone()
-    if user_row is None:
-        print(f"E-mail {user_email} not found", file=sys.stderr)
-        sys.exit(1)
-    uid = user_row.uid
-
     db.execute("SELECT * FROM zoom_meetings WHERE meeting_id=%s", (meeting_id,))
     meeting_row = db.fetchone()
-    if meeting_row is not None:
-        assert meeting_row.host_uid == uid, "Mismatched user ID"
+
+    if meeting_row:
+        db.execute("SELECT * FROM zoom_users WHERE uid=%s", (meeting_row.host_uid,))
+        user_row = db.fetchone()
+        assert user_row
+        print(f"Meeting owned by {user_row.email}")
+        if user_email is not None and user_email != user_row.email:
+            die("Mismatched meeting host!")
+
         print(f"Deleting previous records on meeting {meeting_id}")
         db.execute("DELETE FROM zoom_schedule WHERE mid=%s", (meeting_row.mid,))
         db.execute("DELETE FROM zoom_meetings WHERE mid=%s", (meeting_row.mid,))
 
+    else:
+        if not user_email:
+            die("Meeting is not known yet, you need to specify --user")
+
+        db.execute("SELECT * FROM zoom_users WHERE email=%s", (user_email,))
+        user_row = db.fetchone()
+        if user_row is None:
+            die(f"E-mail {user_email} not found")
+
     meet = get_meeting(user_row.user_id, meeting_id)
-    insert_meeting(uid, meet)
+    insert_meeting(user_row.uid, meet)
 
     db_conn.commit()
 
@@ -164,7 +178,7 @@ def fetch_single(user_email, meeting_id):
 argp = argparse.ArgumentParser(description="Fetch meeting data from Zoom API")
 argp.add_argument('--all', action='store_const', const=True, default=False, help="re-fetch all meetings")
 argp.add_argument('--user', metavar='EMAIL', help='fetch meetings hosted by a given user')
-argp.add_argument('--meeting', type=int, metavar='ID', help='fetch a single meeting (requires --user)')
+argp.add_argument('--meeting', type=int, metavar='ID', help='fetch a single meeting (requires --user unless the meeting is already known)')
 argp.add_argument('--debug', action='store_const', const=True, default=False, help="enable debugging dumps")
 
 args = argp.parse_args()
@@ -173,8 +187,6 @@ debug = args.debug
 if args.all:
     fetch_all()
 elif args.meeting is not None:
-    if args.user is None:
-        argp.error("--meeting requires --user")
     fetch_single(args.user, args.meeting)
 elif args.user is not None:
     raise NotImplementedError