diff --git a/db/db.ddl b/db/db.ddl
index 545ae69dc8433fa0f7e4f7c7ee4e232e0c8f1e2a..78359e6a734ba92cb87e96a4ee660f47a9dc8b4b 100644
--- a/db/db.ddl
+++ b/db/db.ddl
@@ -457,3 +457,12 @@ CREATE TABLE score_tables (
 );
 
 ALTER TABLE contests ADD CONSTRAINT "contests_scoretable_id" FOREIGN KEY (scoretable_id) REFERENCES score_tables(scoretable_id);
+
+-- Odeslané mailové notifikace
+
+CREATE TABLE sent_email (
+	user_id		int		NOT NULL REFERENCES users(user_id) ON DELETE CASCADE,
+	key		varchar(100)	NOT NULL,
+	sent_at		timestamp with time zone	NOT NULL DEFAULT CURRENT_TIMESTAMP,
+	PRIMARY KEY (user_id, key)
+);
diff --git a/db/upgrade-20220115.sql b/db/upgrade-20220115.sql
index 7bf0d633254ed32598fea35064c0f97f1f2cec3f..614710461b1863eb99b150fb59bfe3fdc4eceac4 100644
--- a/db/upgrade-20220115.sql
+++ b/db/upgrade-20220115.sql
@@ -3,3 +3,10 @@ SET ROLE 'mo_osmo';
 ALTER TYPE round_state ADD VALUE 'graded';
 
 ALTER TYPE job_type ADD VALUE 'send_grading_info';
+
+CREATE TABLE sent_email (
+	user_id		int		NOT NULL REFERENCES users(user_id) ON DELETE CASCADE,
+	key		varchar(100)	NOT NULL,
+	sent_at		timestamp with time zone	NOT NULL DEFAULT CURRENT_TIMESTAMP,
+	PRIMARY KEY (user_id, key)
+);
diff --git a/mo/db.py b/mo/db.py
index 919984b3690243fbe23802ab7084c401f95202b9..e5399c40e9cd67c71f5bee2ba005d5aafbba6e01 100644
--- a/mo/db.py
+++ b/mo/db.py
@@ -898,6 +898,16 @@ class ScoreTable(Base):
     contest = relationship('Contest', primaryjoin='Contest.scoretable_id == ScoreTable.scoretable_id')
 
 
+class SentEmail(Base):
+    __tablename__ = 'sent_email'
+
+    user_id = Column(Integer, ForeignKey('users.user_id'), primary_key=True, nullable=False)
+    key = Column(String(100), primary_key=True, nullable=False)
+    sent_at = Column(DateTime(True), nullable=False, server_default=text("CURRENT_TIMESTAMP"))
+
+    user = relationship('User')
+
+
 _engine: Optional[Engine] = None
 _session: Optional[Session] = None
 flask_db: Any = None