diff --git a/briar-api/src/org/briarproject/api/db/MessageHeader.java b/briar-api/src/org/briarproject/api/db/MessageHeader.java
index 4a1b2054b348290dad7343714001d6fb33bcc3bc..6fa1e223f979091b3fdb1e384e82444e40b6facc 100644
--- a/briar-api/src/org/briarproject/api/db/MessageHeader.java
+++ b/briar-api/src/org/briarproject/api/db/MessageHeader.java
@@ -12,11 +12,11 @@ public class MessageHeader {
 	private final Author.Status authorStatus;
 	private final String contentType;
 	private final long timestamp;
-	private final boolean read;
+	private final boolean local, read;
 
 	public MessageHeader(MessageId id, MessageId parent, GroupId groupId,
 			Author author, Author.Status authorStatus, String contentType,
-			long timestamp, boolean read) {
+			long timestamp, boolean local, boolean read) {
 		this.id = id;
 		this.parent = parent;
 		this.groupId = groupId;
@@ -24,6 +24,7 @@ public class MessageHeader {
 		this.authorStatus = authorStatus;
 		this.contentType = contentType;
 		this.timestamp = timestamp;
+		this.local = local;
 		this.read = read;
 	}
 
@@ -69,6 +70,11 @@ public class MessageHeader {
 		return timestamp;
 	}
 
+	/** Returns true if the message was locally generated. */
+	public boolean isLocal() {
+		return local;
+	}
+
 	/** Returns true if the message has been read. */
 	public boolean isRead() {
 		return read;
diff --git a/briar-core/src/org/briarproject/db/Database.java b/briar-core/src/org/briarproject/db/Database.java
index 255a5af2ebeee5a4a8a95234ed57c44acfdfd6de..130c4f1c3f09ecc4f3da410b448b599f384cd646 100644
--- a/briar-core/src/org/briarproject/db/Database.java
+++ b/briar-core/src/org/briarproject/db/Database.java
@@ -124,7 +124,7 @@ interface Database<T> {
 	 * <p>
 	 * Locking: message write.
 	 */
-	void addMessage(T txn, Message m, boolean incoming) throws DbException;
+	void addMessage(T txn, Message m, boolean local) throws DbException;
 
 	/**
 	 * Records that a message has been offered by the given contact.
diff --git a/briar-core/src/org/briarproject/db/DatabaseComponentImpl.java b/briar-core/src/org/briarproject/db/DatabaseComponentImpl.java
index 106e8cab018b516fd7106ab32ae9ae11ee89476c..2ae0579b0147ca065ee7de748b98f33c03f53487 100644
--- a/briar-core/src/org/briarproject/db/DatabaseComponentImpl.java
+++ b/briar-core/src/org/briarproject/db/DatabaseComponentImpl.java
@@ -383,8 +383,12 @@ DatabaseCleaner.Callback {
 	 */
 	private void addMessage(T txn, Message m, ContactId sender)
 			throws DbException {
-		db.addMessage(txn, m, sender != null);
-		if(sender == null) db.setReadFlag(txn, m.getId(), true);
+		if(sender == null) {
+			db.addMessage(txn, m, true);
+			db.setReadFlag(txn, m.getId(), true);
+		} else {
+			db.addMessage(txn, m, false);
+		}
 		Group g = m.getGroup();
 		Collection<ContactId> visibility = db.getVisibility(txn, g.getId());
 		visibility = new HashSet<ContactId>(visibility);
diff --git a/briar-core/src/org/briarproject/db/JdbcDatabase.java b/briar-core/src/org/briarproject/db/JdbcDatabase.java
index a2dd5ac86db2aa541d7bafe21e2cd6d10d744ada..9c660107971540f371306ec42f105a0c7ff3884a 100644
--- a/briar-core/src/org/briarproject/db/JdbcDatabase.java
+++ b/briar-core/src/org/briarproject/db/JdbcDatabase.java
@@ -60,8 +60,8 @@ import org.briarproject.api.transport.TemporarySecret;
  */
 abstract class JdbcDatabase implements Database<Connection> {
 
-	private static final int SCHEMA_VERSION = 3;
-	private static final int MIN_SCHEMA_VERSION = 3;
+	private static final int SCHEMA_VERSION = 4;
+	private static final int MIN_SCHEMA_VERSION = 4;
 
 	private static final String CREATE_SETTINGS =
 			"CREATE TABLE settings"
@@ -160,7 +160,7 @@ abstract class JdbcDatabase implements Database<Connection> {
 					+ " bodyStart INT NOT NULL,"
 					+ " bodyLength INT NOT NULL,"
 					+ " raw BLOB NOT NULL,"
-					+ " incoming BOOLEAN NOT NULL,"
+					+ " local BOOLEAN NOT NULL,"
 					+ " read BOOLEAN NOT NULL,"
 					+ " PRIMARY KEY (messageId),"
 					+ " FOREIGN KEY (groupId)"
@@ -805,14 +805,14 @@ abstract class JdbcDatabase implements Database<Connection> {
 		}
 	}
 
-	public void addMessage(Connection txn, Message m, boolean incoming)
+	public void addMessage(Connection txn, Message m, boolean local)
 			throws DbException {
 		PreparedStatement ps = null;
 		try {
 			String sql = "INSERT INTO messages (messageId, parentId, groupId,"
 					+ " authorId, authorName, authorKey, contentType,"
 					+ " timestamp, length, bodyStart, bodyLength, raw,"
-					+ " incoming, read)"
+					+ " local, read)"
 					+ " VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, FALSE)";
 			ps = txn.prepareStatement(sql);
 			ps.setBytes(1, m.getId().getBytes());
@@ -836,7 +836,7 @@ abstract class JdbcDatabase implements Database<Connection> {
 			ps.setInt(10, m.getBodyStart());
 			ps.setInt(11, m.getBodyLength());
 			ps.setBytes(12, raw);
-			ps.setBoolean(13, incoming);
+			ps.setBoolean(13, local);
 			int affected = ps.executeUpdate();
 			if(affected != 1) throw new DbStateException();
 			ps.close();
@@ -1517,7 +1517,7 @@ abstract class JdbcDatabase implements Database<Connection> {
 			if(rs.next()) throw new DbException();
 			// Get the message headers
 			sql = "SELECT messageId, parentId, m.groupId, contentType,"
-					+ " timestamp, incoming, read"
+					+ " timestamp, local, read"
 					+ " FROM messages AS m"
 					+ " JOIN groups AS g"
 					+ " ON m.groupId = g.groupId"
@@ -1536,16 +1536,16 @@ abstract class JdbcDatabase implements Database<Connection> {
 				GroupId groupId = new GroupId(rs.getBytes(3));
 				String contentType = rs.getString(4);
 				long timestamp = rs.getLong(5);
-				boolean incoming = rs.getBoolean(6);
+				boolean local = rs.getBoolean(6);
 				boolean read = rs.getBoolean(7);
-				if(incoming) {
+				if(local) {
 					headers.add(new MessageHeader(id, parent, groupId,
-							remoteAuthor, VERIFIED, contentType, timestamp,
-							read));
+							localAuthor, VERIFIED, contentType, timestamp,
+							true, read));
 				} else {
 					headers.add(new MessageHeader(id, parent, groupId,
-							localAuthor, VERIFIED, contentType, timestamp,
-							read));
+							remoteAuthor, VERIFIED, contentType, timestamp,
+							false, read));
 				}
 			}
 			rs.close();
@@ -1719,7 +1719,7 @@ abstract class JdbcDatabase implements Database<Connection> {
 		ResultSet rs = null;
 		try {
 			String sql = "SELECT messageId, parentId, m.authorId, authorName,"
-					+ " authorKey, contentType, timestamp, read,"
+					+ " authorKey, contentType, timestamp, local, read,"
 					+ " la.authorId IS NOT NULL, c.authorId IS NOT NULL"
 					+ " FROM messages AS m"
 					+ " LEFT OUTER JOIN localAuthors AS la"
@@ -1747,15 +1747,16 @@ abstract class JdbcDatabase implements Database<Connection> {
 				}
 				String contentType = rs.getString(6);
 				long timestamp = rs.getLong(7);
-				boolean read = rs.getBoolean(8);
-				boolean isSelf = rs.getBoolean(9);
-				boolean isContact = rs.getBoolean(10);
+				boolean local = rs.getBoolean(8);
+				boolean read = rs.getBoolean(9);
+				boolean isSelf = rs.getBoolean(10);
+				boolean isContact = rs.getBoolean(11);
 				Author.Status authorStatus;
 				if(author == null) authorStatus = ANONYMOUS;
 				else if(isSelf || isContact) authorStatus = VERIFIED;
 				else authorStatus = UNKNOWN;
 				headers.add(new MessageHeader(id, parent, g, author,
-						authorStatus, contentType, timestamp, read));
+						authorStatus, contentType, timestamp, local, read));
 			}
 			rs.close();
 			ps.close();
diff --git a/briar-tests/src/org/briarproject/db/DatabaseComponentTest.java b/briar-tests/src/org/briarproject/db/DatabaseComponentTest.java
index 65431b633b6ef4176dfa3ec756c703478408034c..44bca26f2f4b276519eac41fd09eecad2946054f 100644
--- a/briar-tests/src/org/briarproject/db/DatabaseComponentTest.java
+++ b/briar-tests/src/org/briarproject/db/DatabaseComponentTest.java
@@ -286,7 +286,7 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
 			will(returnValue(false));
 			oneOf(database).containsGroup(txn, groupId);
 			will(returnValue(true));
-			oneOf(database).addMessage(txn, message, false);
+			oneOf(database).addMessage(txn, message, true);
 			oneOf(database).setReadFlag(txn, messageId, true);
 			oneOf(database).getVisibility(txn, groupId);
 			will(returnValue(Arrays.asList(contactId)));
@@ -1000,7 +1000,7 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
 			will(returnValue(false));
 			oneOf(database).containsVisibleGroup(txn, contactId, groupId);
 			will(returnValue(true));
-			oneOf(database).addMessage(txn, message, true);
+			oneOf(database).addMessage(txn, message, false);
 			oneOf(database).getVisibility(txn, groupId);
 			will(returnValue(Arrays.asList(contactId)));
 			oneOf(database).getContactIds(txn);
diff --git a/briar-tests/src/org/briarproject/db/H2DatabaseTest.java b/briar-tests/src/org/briarproject/db/H2DatabaseTest.java
index 37a4c944f2d572ffb16dde52ef5fb2a1722d6928..103d12e252665d0bf9984ed96198280f555cc2ed 100644
--- a/briar-tests/src/org/briarproject/db/H2DatabaseTest.java
+++ b/briar-tests/src/org/briarproject/db/H2DatabaseTest.java
@@ -145,7 +145,7 @@ public class H2DatabaseTest extends BriarTestCase {
 
 		// Subscribe to a group and store a message
 		db.addGroup(txn, group);
-		db.addMessage(txn, message, false);
+		db.addMessage(txn, message, true);
 
 		// Unsubscribing from the group should remove the message
 		assertTrue(db.containsMessage(txn, messageId));
@@ -167,7 +167,7 @@ public class H2DatabaseTest extends BriarTestCase {
 		db.addGroup(txn, group);
 		db.addVisibility(txn, contactId, groupId);
 		db.setGroups(txn, contactId, Arrays.asList(group), 1);
-		db.addMessage(txn, message, false);
+		db.addMessage(txn, message, true);
 
 		// The message has no status yet, so it should not be sendable
 		Collection<MessageId> ids = db.getMessagesToSend(txn, contactId,
@@ -202,7 +202,7 @@ public class H2DatabaseTest extends BriarTestCase {
 		assertEquals(contactId, db.addContact(txn, author, localAuthorId));
 		db.addGroup(txn, group);
 		db.addVisibility(txn, contactId, groupId);
-		db.addMessage(txn, message, false);
+		db.addMessage(txn, message, true);
 		db.addStatus(txn, contactId, messageId, false, false);
 
 		// The contact is not subscribed, so the message should not be sendable
@@ -239,7 +239,7 @@ public class H2DatabaseTest extends BriarTestCase {
 		db.addGroup(txn, group);
 		db.addVisibility(txn, contactId, groupId);
 		db.setGroups(txn, contactId, Arrays.asList(group), 1);
-		db.addMessage(txn, message, false);
+		db.addMessage(txn, message, true);
 		db.addStatus(txn, contactId, messageId, false, false);
 
 		// The message is sendable, but too large to send
@@ -269,7 +269,7 @@ public class H2DatabaseTest extends BriarTestCase {
 		assertEquals(contactId, db.addContact(txn, author, localAuthorId));
 		db.addGroup(txn, group);
 		db.setGroups(txn, contactId, Arrays.asList(group), 1);
-		db.addMessage(txn, message, false);
+		db.addMessage(txn, message, true);
 		db.addStatus(txn, contactId, messageId, false, false);
 
 		// The subscription is not visible to the contact, so the message
@@ -306,10 +306,10 @@ public class H2DatabaseTest extends BriarTestCase {
 		MessageId messageId1 = new MessageId(TestUtils.getRandomId());
 		Message message1 = new TestMessage(messageId1, null, group, author,
 				contentType, subject, timestamp, raw);
-		db.addMessage(txn, message, false);
+		db.addMessage(txn, message, true);
 		db.addStatus(txn, contactId, messageId, false, true);
 		db.raiseAckFlag(txn, contactId, messageId);
-		db.addMessage(txn, message1, false);
+		db.addMessage(txn, message1, true);
 		db.addStatus(txn, contactId, messageId1, false, true);
 		db.raiseAckFlag(txn, contactId, messageId1);
 
@@ -340,7 +340,7 @@ public class H2DatabaseTest extends BriarTestCase {
 		db.setGroups(txn, contactId, Arrays.asList(group), 1);
 
 		// Receive the same message twice
-		db.addMessage(txn, message, false);
+		db.addMessage(txn, message, true);
 		db.addStatus(txn, contactId, messageId, false, true);
 		db.raiseAckFlag(txn, contactId, messageId);
 		db.raiseAckFlag(txn, contactId, messageId);
@@ -371,7 +371,7 @@ public class H2DatabaseTest extends BriarTestCase {
 		db.addGroup(txn, group);
 		db.addVisibility(txn, contactId, groupId);
 		db.setGroups(txn, contactId, Arrays.asList(group), 1);
-		db.addMessage(txn, message, false);
+		db.addMessage(txn, message, true);
 		db.addStatus(txn, contactId, messageId, false, false);
 
 		// Retrieve the message from the database and mark it as sent
@@ -407,8 +407,8 @@ public class H2DatabaseTest extends BriarTestCase {
 
 		// Subscribe to a group and store two messages
 		db.addGroup(txn, group);
-		db.addMessage(txn, message, false);
-		db.addMessage(txn, message1, false);
+		db.addMessage(txn, message, true);
+		db.addMessage(txn, message1, true);
 
 		// Allowing enough capacity for one message should return the older one
 		Iterator<MessageId> it = db.getOldMessages(txn, size).iterator();
@@ -446,7 +446,7 @@ public class H2DatabaseTest extends BriarTestCase {
 		// Storing a message should reduce the free space
 		Connection txn = db.startTransaction();
 		db.addGroup(txn, group);
-		db.addMessage(txn, message, false);
+		db.addMessage(txn, message, true);
 		db.commitTransaction(txn);
 		assertTrue(db.getFreeSpace() < free);
 
@@ -705,7 +705,7 @@ public class H2DatabaseTest extends BriarTestCase {
 		assertEquals(contactId, db.addContact(txn, author, localAuthorId));
 		db.addGroup(txn, group);
 		db.setGroups(txn, contactId, Arrays.asList(group), 1);
-		db.addMessage(txn, message, false);
+		db.addMessage(txn, message, true);
 		db.addStatus(txn, contactId, messageId, false, false);
 
 		// The subscription is not visible
@@ -752,7 +752,7 @@ public class H2DatabaseTest extends BriarTestCase {
 		MessageId childId = new MessageId(TestUtils.getRandomId());
 		Message child = new TestMessage(childId, null, group, null, contentType,
 				subject, timestamp, raw);
-		db.addMessage(txn, child, false);
+		db.addMessage(txn, child, true);
 		assertTrue(db.containsMessage(txn, childId));
 		assertNull(db.getParent(txn, childId));
 
@@ -773,7 +773,7 @@ public class H2DatabaseTest extends BriarTestCase {
 		MessageId parentId = new MessageId(TestUtils.getRandomId());
 		Message child = new TestMessage(childId, parentId, group, null,
 				contentType, subject, timestamp, raw);
-		db.addMessage(txn, child, false);
+		db.addMessage(txn, child, true);
 		assertTrue(db.containsMessage(txn, childId));
 		assertFalse(db.containsMessage(txn, parentId));
 		assertNull(db.getParent(txn, childId));
@@ -801,8 +801,8 @@ public class H2DatabaseTest extends BriarTestCase {
 				contentType, subject, timestamp, raw);
 		Message parent = new TestMessage(parentId, null, group1, null,
 				contentType, subject, timestamp, raw);
-		db.addMessage(txn, child, false);
-		db.addMessage(txn, parent, false);
+		db.addMessage(txn, child, true);
+		db.addMessage(txn, parent, true);
 		assertTrue(db.containsMessage(txn, childId));
 		assertTrue(db.containsMessage(txn, parentId));
 		assertNull(db.getParent(txn, childId));
@@ -826,8 +826,8 @@ public class H2DatabaseTest extends BriarTestCase {
 				contentType, subject, timestamp, raw);
 		Message parent = new TestMessage(parentId, null, group, null,
 				contentType, subject, timestamp, raw);
-		db.addMessage(txn, child, false);
-		db.addMessage(txn, parent, false);
+		db.addMessage(txn, child, true);
+		db.addMessage(txn, parent, true);
 		assertTrue(db.containsMessage(txn, childId));
 		assertTrue(db.containsMessage(txn, parentId));
 		assertEquals(parentId, db.getParent(txn, childId));
@@ -853,8 +853,8 @@ public class H2DatabaseTest extends BriarTestCase {
 		MessageId messageId1 = new MessageId(TestUtils.getRandomId());
 		Message message1 = new TestMessage(messageId1, null, group, null,
 				contentType, subject, timestamp, raw, 10, bodyLength);
-		db.addMessage(txn, message, false);
-		db.addMessage(txn, message1, false);
+		db.addMessage(txn, message, true);
+		db.addMessage(txn, message1, true);
 
 		// Calculate the expected message bodies
 		byte[] expectedBody = new byte[bodyLength];
@@ -887,13 +887,13 @@ public class H2DatabaseTest extends BriarTestCase {
 		db.addGroup(txn, group);
 
 		// Store a couple of messages
-		db.addMessage(txn, message, false);
+		db.addMessage(txn, message, true);
 		MessageId messageId1 = new MessageId(TestUtils.getRandomId());
 		MessageId parentId = new MessageId(TestUtils.getRandomId());
 		long timestamp1 = System.currentTimeMillis();
 		Message message1 = new TestMessage(messageId1, parentId, group, author,
 				contentType, subject, timestamp1, raw);
-		db.addMessage(txn, message1, false);
+		db.addMessage(txn, message1, true);
 		// Mark one of the messages read
 		db.setReadFlag(txn, messageId, true);
 
@@ -944,7 +944,7 @@ public class H2DatabaseTest extends BriarTestCase {
 		db.addGroup(txn, group);
 
 		// Store a message from the contact - status VERIFIED
-		db.addMessage(txn, message, false);
+		db.addMessage(txn, message, true);
 		AuthorId authorId1 = new AuthorId(TestUtils.getRandomId());
 		// Store a message from an unknown author - status UNKNOWN
 		Author author1 = new Author(authorId1, "Bob",
@@ -952,12 +952,12 @@ public class H2DatabaseTest extends BriarTestCase {
 		MessageId messageId1 = new MessageId(TestUtils.getRandomId());
 		Message message1 = new TestMessage(messageId1, null, group, author1,
 				contentType, subject, timestamp, raw);
-		db.addMessage(txn, message1, false);
+		db.addMessage(txn, message1, true);
 		// Store an anonymous message - status ANONYMOUS
 		MessageId messageId2 = new MessageId(TestUtils.getRandomId());
 		Message message2 = new TestMessage(messageId2, null, group, null,
 				contentType, subject, timestamp, raw);
-		db.addMessage(txn, message2, false);
+		db.addMessage(txn, message2, true);
 
 		// Retrieve the message headers (order is undefined)
 		Collection<MessageHeader> headers = db.getMessageHeaders(txn, groupId);
@@ -996,7 +996,7 @@ public class H2DatabaseTest extends BriarTestCase {
 
 		// Subscribe to a group and store a message
 		db.addGroup(txn, group);
-		db.addMessage(txn, message, false);
+		db.addMessage(txn, message, true);
 
 		// The message should be unread by default
 		assertFalse(db.getReadFlag(txn, messageId));
@@ -1026,17 +1026,17 @@ public class H2DatabaseTest extends BriarTestCase {
 		db.addGroup(txn, group1);
 
 		// Store two messages in the first group
-		db.addMessage(txn, message, false);
+		db.addMessage(txn, message, true);
 		MessageId messageId1 = new MessageId(TestUtils.getRandomId());
 		Message message1 = new TestMessage(messageId1, null, group, author,
 				contentType, subject, timestamp, raw);
-		db.addMessage(txn, message1, false);
+		db.addMessage(txn, message1, true);
 
 		// Store one message in the second group
 		MessageId messageId2 = new MessageId(TestUtils.getRandomId());
 		Message message2 = new TestMessage(messageId2, null, group1, author,
 				contentType, subject, timestamp, raw);
-		db.addMessage(txn, message2, false);
+		db.addMessage(txn, message2, true);
 
 		// Mark one of the messages in the first group read
 		db.setReadFlag(txn, messageId, true);
@@ -1531,7 +1531,7 @@ public class H2DatabaseTest extends BriarTestCase {
 				db.getInboxMessageHeaders(txn, contactId));
 
 		// Add a message to the inbox group - the header should be returned
-		db.addMessage(txn, message, false);
+		db.addMessage(txn, message, true);
 		Collection<MessageHeader> headers =
 				db.getInboxMessageHeaders(txn, contactId);
 		assertEquals(1, headers.size());