Database design for email messaging system

36,611

Solution 1

You need to split your table for it. You could have following schema and structure

CREATE TABLE [Users]
    (
      [UserID] INT ,
      [UserName] NVARCHAR(50) ,
      [FirstName] NVARCHAR(50) ,
      [LastName] NVARCHAR(50)
    )

CREATE TABLE [Messages]
    (
      [MessageID] INT ,
      [Subject] NVARCHAR(MAX) ,
      [Body] NVARCHAR(MAX) ,
      [Date] DATETIME,
      [AuthorID] INT,
    )

CREATE TABLE [MessagePlaceHolders]
    (
      [PlaceHolderID] INT ,
      [PlaceHolder] NVARCHAR(255)--For example: InBox, SentItems, Draft, Trash, Spam 
    )

CREATE TABLE [Users_Messages_Mapped]
    (
      [MessageID] INT ,
      [UserID] INT ,
      [PlaceHolderID] INT,
      [IsRead] BIT ,
      [IsStarred] BIT 

    )

In users table you can have users."Messages" denotes the table for messages. "MessagePlaceHolders" denotes the table for placeholders for messages. Placeholders can be inbox, sent item, draft, spam or trash. "Users_Messages_Mapped" denotes the mapping table for users and messages. The "UserID" and "PlaceHolderID" are the foreign keys."IsRead" and "IsStarred" signifies what their name stands for. If there is no record found for a particular messageid in "Users_Messages_Mapped" table that record will be deleted from Messages table since we no longer need it.

Solution 2

If you're doing document-orientated work, I suggest taking a look at CouchDB. It is schema-less, meaning issues like this disappear.

Let's take a look at the example: A sends a message to B, and it's deleted by B.

You would have a single instance of the document, with recipients listed as an attribute of the email. As users delete messages, you either remove them from the recipients list or add them to a list of deleted_by or whatever you choose.

It's a much different approach to data than what you're used to, but may be highly beneficial to take some time to consider.

Solution 3

I think you need to decompose your schema some more. Store emails seperately, and map inboxes to the messages they contain.

Solution 4

If I were you I would set two flags one for sender and other one for receiver if both flags are true then message should be deleted from database otherwise keep that in database but hide it from who deleted it.

Do same thing for trash. You may want to run cron or check manually if both sender and receiver delete the message then remove it from database.

Solution 5

A message can only be in one folder at a time, so you want a folders table (containing folders 'Trash', 'Inbox', 'Archive', etc.) and a foreign key from messages to folders. For labels, you have a many-to-many relation, so you need a labels table and also a link table (messages_labels). For starring, a simple bit column should do, same for 'unread'.

Share:
36,611

Related videos on Youtube

AsifQadri
Author by

AsifQadri

People often say that motivation doesn't last. Well, neither does bathing - that's why we recommend it daily.

Updated on July 09, 2022

Comments

  • AsifQadri
    AsifQadri almost 2 years

    I want to make an email messaging system like gmail have. I would like to have following option: Starred, Trash, Spam, Draft, Read, Unread. Right now I have the below following structure in my database :

    CREATE TABLE [MyInbox](
        [InboxID] [int] IDENTITY(1,1) NOT NULL,
        [FromUserID] [int] NOT NULL,
        [ToUserID] [int] NOT NULL,
        [Created] [datetime] NOT NULL,
        [Subject] [nvarchar](255) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
        [Body] [nvarchar](max) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
        [IsRead] [bit] NOT NULL,
        [IsReceived] [bit] NOT NULL,
        [IsSent] [bit] NOT NULL,
        [IsStar] [bit] NOT NULL CONSTRAINT [DF_MyInbox_IsStarred]  DEFAULT ((0)),
        [IsTrash] [bit] NOT NULL CONSTRAINT [DF_MyInbox_IsTrashed]  DEFAULT ((0)),
        [IsDraft] [bit] NOT NULL CONSTRAINT [DF_MyInbox_Isdrafted]  DEFAULT ((0))
    ) ON [PRIMARY]
    

    But I am facing some issues with the above structure. Right now if a user A sends a msessage to user B I am storing a row in this table But if user B deletes the that message it gets deleted frm user's A sent message too. This is wrong, I want exactly as normal email messaging system does. If A deletes message from his sent item then B should not get deleted from his inbox. I am thinking on other problem here which will come suppose a user A sent a mail to 500 users at once so as per my design I will have 500 rows with duplicate bodies i.e not a memory efficent way to store it. Could you guys please help me in makeing the design for a messaging system ?

  • zarpio
    zarpio about 10 years
    Can you please describe, how can we know in this design that which is from-user and to-user whom message is being sent.
  • Adam C.
    Adam C. about 10 years
    @zarpio the authorID in message table is sender ID.
  • user3308043
    user3308043 almost 10 years
    Should you not have a composite key in the Users_Messages_Mapped table?
  • naf4me
    naf4me over 7 years
    @raghav, How can it create threaded mail system? Or it will not work fir threaded mail?
  • Alvaro Castro
    Alvaro Castro over 7 years
    useful diagram and great solution schema..only have to mention that for the table Messages the column "AuthorId" is redundant cause you already have it identified in the Intermediate table.
  • Brian
    Brian about 7 years
    Does this support a message to be sent to multiple users?
  • Smith
    Smith almost 6 years
    @Raghav What if the message would be coming from two types of people, employee and customers?
  • Dexter
    Dexter over 5 years
    @zarpio the [AuthorID] is the the Sent user, and [UserID] is the receiver.
  • Raghav
    Raghav over 5 years
    @Smith you can have one more column in Messages Table say MessageTypeID INT
  • Abhi
    Abhi about 4 years
    This is a very good guideline reply that helped refine a couple of things on my design. :)
  • user207421
    user207421 over 3 years
    And you therefore still have exactly the same problem the OP is asking about, unless there is more to your solution than this, such as separate folders.