diff --git a/bindings/fileTransfer.go b/bindings/fileTransfer.go
index 2ed9f9b02c9999dd11c3685bc20a3612d9d49bf9..5de3d5d3e91892eb0ea63c77827498c1371a1159 100644
--- a/bindings/fileTransfer.go
+++ b/bindings/fileTransfer.go
@@ -38,8 +38,8 @@ type FileTransferReceivedProgressFunc interface {
 // receiver of an incoming file transfer. It is called on the reception of the
 // initial file transfer message.
 type FileTransferReceiveFunc interface {
-	ReceiveCallback(tid []byte, fileName string, sender []byte, size int,
-		preview []byte)
+	ReceiveCallback(tid []byte, fileName, fileType string, sender []byte,
+		size int, preview []byte)
 }
 
 // NewFileTransferManager creates a new file transfer manager and starts the
@@ -50,10 +50,10 @@ type FileTransferReceiveFunc interface {
 func NewFileTransferManager(client *Client, receiveFunc FileTransferReceiveFunc,
 	parameters string) (FileTransfer, error) {
 
-	receiveCB := func(tid ftCrypto.TransferID, fileName string, sender *id.ID,
-		size uint32, preview []byte) {
+	receiveCB := func(tid ftCrypto.TransferID, fileName, fileType string,
+		sender *id.ID, size uint32, preview []byte) {
 		receiveFunc.ReceiveCallback(
-			tid.Bytes(), fileName, sender.Bytes(), int(size), preview)
+			tid.Bytes(), fileName, fileType, sender.Bytes(), int(size), preview)
 	}
 
 	// JSON unmarshal parameters string
@@ -83,7 +83,9 @@ func NewFileTransferManager(client *Client, receiveFunc FileTransferReceiveFunc,
 // Send sends a file to the recipient. The sender must have an E2E relationship
 // with the recipient.
 // The file name is the name of the file to show a user. It has a max length of
-// 32 bytes.
+// 48 bytes.
+// The file type identifies what type of file is being sent. It has a max length
+// of 8 bytes.
 // The file data cannot be larger than 4 mB
 // The retry float is the total amount of data to send relative to the data
 // size. Data will be resent on error and will resend up to [(1 + retry) *
@@ -93,9 +95,9 @@ func NewFileTransferManager(client *Client, receiveFunc FileTransferReceiveFunc,
 // Returns a unique transfer ID used to identify the transfer.
 // PeriodMS is the duration, in milliseconds, to wait between progress callback
 // calls. Set this large enough to prevent spamming.
-func (f FileTransfer) Send(fileName string, fileData []byte, recipientID []byte,
-	retry float32, preview []byte, progressFunc FileTransferSentProgressFunc,
-	periodMS int) ([]byte, error) {
+func (f FileTransfer) Send(fileName, fileType string, fileData []byte,
+	recipientID []byte, retry float32, preview []byte,
+	progressFunc FileTransferSentProgressFunc, periodMS int) ([]byte, error) {
 
 	// Create SentProgressCallback
 	progressCB := func(completed bool, sent, arrived, total uint16, err error) {
@@ -113,8 +115,8 @@ func (f FileTransfer) Send(fileName string, fileData []byte, recipientID []byte,
 	period := time.Duration(periodMS) * time.Millisecond
 
 	// Send file
-	tid, err := f.m.Send(
-		fileName, fileData, recipient, retry, preview, progressCB, period)
+	tid, err := f.m.Send(fileName, fileType, fileData, recipient, retry,
+		preview, progressCB, period)
 	if err != nil {
 		return nil, err
 	}
@@ -129,7 +131,7 @@ func (f FileTransfer) Send(fileName string, fileData []byte, recipientID []byte,
 // It will then call every time a file part is sent, a file part arrives, the
 // transfer completes, or an error occurs. It is called at most once every
 // period, which means if events occur faster than the period, then they will
-// not be reported and instead the progress will be reported once at the end of
+// not be reported and instead, the progress will be reported once at the end of
 // the period.
 // The period is specified in milliseconds.
 func (f FileTransfer) RegisterSendProgressCallback(transferID []byte,
@@ -150,7 +152,8 @@ func (f FileTransfer) RegisterSendProgressCallback(transferID []byte,
 	return f.m.RegisterSendProgressCallback(tid, progressCB, period)
 }
 
-// Resend resends a file if Send fails.
+// Resend resends a file if sending fails. This function should only be called
+//if the interfaces.SentProgressCallback returns an error.
 func (f FileTransfer) Resend(transferID []byte) error {
 	// Unmarshal transfer ID
 	tid := ftCrypto.UnmarshalTransferID(transferID)
@@ -174,7 +177,7 @@ func (f FileTransfer) CloseSend(transferID []byte) error {
 // transfer. It will then call every time a file part is received, the transfer
 // completes, or an error occurs. It is called at most once ever period, which
 // means if events occur faster than the period, then they will not be reported
-// and instead the progress will be reported once at the end of the period.
+// and instead, the progress will be reported once at the end of the period.
 // Once the callback reports that the transfer has completed, the recipient
 // can get the full file by calling Receive.
 // The period is specified in milliseconds.
@@ -221,6 +224,12 @@ func (f FileTransfer) GetMaxFileNameByteLength() int {
 	return ft.FileNameMaxLen
 }
 
+// GetMaxFileTypeByteLength returns the maximum length, in bytes, allowed for a
+// file type.
+func (f FileTransfer) GetMaxFileTypeByteLength() int {
+	return ft.FileTypeMaxLen
+}
+
 // GetMaxFileSize returns the maximum file size, in bytes, allowed to be
 // transferred.
 func (f FileTransfer) GetMaxFileSize() int {
diff --git a/cmd/fileTransfer.go b/cmd/fileTransfer.go
index 5ba84a18cbc7ab6df98d0282e3f2748063dc55e5..71ae0842345ab93200a51a26c668e1bed5774b7d 100644
--- a/cmd/fileTransfer.go
+++ b/cmd/fileTransfer.go
@@ -81,11 +81,12 @@ var ftCmd = &cobra.Command{
 		if viper.IsSet("sendFile") {
 			recipientContactPath := viper.GetString("sendFile")
 			filePath := viper.GetString("filePath")
+			fileType := viper.GetString("fileType")
 			filePreviewPath := viper.GetString("filePreviewPath")
 			filePreviewString := viper.GetString("filePreviewString")
 			retry := float32(viper.GetFloat64("retry"))
 
-			sendFile(filePath, filePreviewPath, filePreviewString,
+			sendFile(filePath, fileType, filePreviewPath, filePreviewString,
 				recipientContactPath, retry, m, sendDone)
 		}
 
@@ -123,6 +124,7 @@ var ftCmd = &cobra.Command{
 type receivedFtResults struct {
 	tid      ftCrypto.TransferID
 	fileName string
+	fileType string
 	sender   *id.ID
 	size     uint32
 	preview  []byte
@@ -136,9 +138,10 @@ func initFileTransferManager(client *api.Client, maxThroughput int) (
 
 	// Create interfaces.ReceiveCallback that returns the results on a channel
 	receiveChan := make(chan receivedFtResults, 100)
-	receiveCB := func(tid ftCrypto.TransferID, fileName string, sender *id.ID,
-		size uint32, preview []byte) {
-		receiveChan <- receivedFtResults{tid, fileName, sender, size, preview}
+	receiveCB := func(tid ftCrypto.TransferID, fileName, fileType string,
+		sender *id.ID, size uint32, preview []byte) {
+		receiveChan <- receivedFtResults{
+			tid, fileName, fileType, sender, size, preview}
 	}
 
 	// Create new parameters
@@ -163,7 +166,7 @@ func initFileTransferManager(client *api.Client, maxThroughput int) (
 }
 
 // sendFile sends the file to the recipient and prints the progress.
-func sendFile(filePath, filePreviewPath, filePreviewString,
+func sendFile(filePath, fileType, filePreviewPath, filePreviewString,
 	recipientContactPath string, retry float32, m *ft.Manager,
 	done chan struct{}) {
 
@@ -211,8 +214,8 @@ func sendFile(filePath, filePreviewPath, filePreviewString,
 	}
 
 	// Send the file
-	_, err = m.Send(filePath, fileData, recipient.ID, retry, filePreviewData,
-		progressCB, callbackPeriod)
+	_, err = m.Send(filePath, fileType, fileData, recipient.ID, retry,
+		filePreviewData, progressCB, callbackPeriod)
 	if err != nil {
 		jww.FATAL.Panicf("Failed to send file %q to %s: %+v",
 			filePath, recipient.ID, err)
@@ -305,6 +308,10 @@ func init() {
 		"The path to the file to send. Also used as the file name.")
 	bindPFlagCheckErr("filePath")
 
+	ftCmd.Flags().String("fileType", "txt",
+		"8-byte file type.")
+	bindPFlagCheckErr("filePath")
+
 	ftCmd.Flags().String("filePreviewPath", "",
 		"The path to the file preview to send. Set either this flag or "+
 			"filePreviewString.")
diff --git a/fileTransfer/ftMessages.pb.go b/fileTransfer/ftMessages.pb.go
index 6ca9bdba1d70a40232bab6e7b77eae833defb9e9..b874f6fcf71cc4ade1b4fbc3ef315298e1bd58ed 100644
--- a/fileTransfer/ftMessages.pb.go
+++ b/fileTransfer/ftMessages.pb.go
@@ -1,131 +1,218 @@
+///////////////////////////////////////////////////////////////////////////////
+// Copyright © 2020 xx network SEZC                                          //
+//                                                                           //
+// Use of this source code is governed by a license that can be found in the //
+// LICENSE file                                                              //
+///////////////////////////////////////////////////////////////////////////////
+
 // Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// 	protoc-gen-go v1.26.0
+// 	protoc        v3.17.3
 // source: fileTransfer/ftMessages.proto
 
 package fileTransfer
 
 import (
-	fmt "fmt"
-	proto "github.com/golang/protobuf/proto"
-	math "math"
+	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+	reflect "reflect"
+	sync "sync"
 )
 
-// Reference imports to suppress errors if they are not otherwise used.
-var _ = proto.Marshal
-var _ = fmt.Errorf
-var _ = math.Inf
-
-// This is a compile-time assertion to ensure that this generated file
-// is compatible with the proto package it is being compiled against.
-// A compilation error at this line likely means your copy of the
-// proto package needs to be updated.
-const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
+const (
+	// Verify that this generated code is sufficiently up-to-date.
+	_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
+	// Verify that runtime/protoimpl is sufficiently up-to-date.
+	_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
+)
 
 type NewFileTransfer struct {
-	FileName             string   `protobuf:"bytes,1,opt,name=fileName,proto3" json:"fileName,omitempty"`
-	TransferKey          []byte   `protobuf:"bytes,2,opt,name=transferKey,proto3" json:"transferKey,omitempty"`
-	TransferMac          []byte   `protobuf:"bytes,3,opt,name=transferMac,proto3" json:"transferMac,omitempty"`
-	NumParts             uint32   `protobuf:"varint,4,opt,name=numParts,proto3" json:"numParts,omitempty"`
-	Size                 uint32   `protobuf:"varint,5,opt,name=size,proto3" json:"size,omitempty"`
-	Retry                float32  `protobuf:"fixed32,6,opt,name=retry,proto3" json:"retry,omitempty"`
-	Preview              []byte   `protobuf:"bytes,7,opt,name=preview,proto3" json:"preview,omitempty"`
-	XXX_NoUnkeyedLiteral struct{} `json:"-"`
-	XXX_unrecognized     []byte   `json:"-"`
-	XXX_sizecache        int32    `json:"-"`
-}
-
-func (m *NewFileTransfer) Reset()         { *m = NewFileTransfer{} }
-func (m *NewFileTransfer) String() string { return proto.CompactTextString(m) }
-func (*NewFileTransfer) ProtoMessage()    {}
-func (*NewFileTransfer) Descriptor() ([]byte, []int) {
-	return fileDescriptor_9d574f363dd34365, []int{0}
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	FileName    string  `protobuf:"bytes,1,opt,name=fileName,proto3" json:"fileName,omitempty"`       // Name of the file; max 32 characters
+	FileType    string  `protobuf:"bytes,2,opt,name=fileType,proto3" json:"fileType,omitempty"`       // Type of file; max 8 characters
+	TransferKey []byte  `protobuf:"bytes,3,opt,name=transferKey,proto3" json:"transferKey,omitempty"` // 256 bit encryption key to identify the transfer
+	TransferMac []byte  `protobuf:"bytes,4,opt,name=transferMac,proto3" json:"transferMac,omitempty"` // 256 bit MAC of the entire file
+	NumParts    uint32  `protobuf:"varint,5,opt,name=numParts,proto3" json:"numParts,omitempty"`      // Number of file parts
+	Size        uint32  `protobuf:"varint,6,opt,name=size,proto3" json:"size,omitempty"`              // The size of the file; max of 4 mB
+	Retry       float32 `protobuf:"fixed32,7,opt,name=retry,proto3" json:"retry,omitempty"`           // Used to determine how many times to retry sending
+	Preview     []byte  `protobuf:"bytes,8,opt,name=preview,proto3" json:"preview,omitempty"`         // A preview of the file; max of 4 kB
+}
+
+func (x *NewFileTransfer) Reset() {
+	*x = NewFileTransfer{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_fileTransfer_ftMessages_proto_msgTypes[0]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
 }
 
-func (m *NewFileTransfer) XXX_Unmarshal(b []byte) error {
-	return xxx_messageInfo_NewFileTransfer.Unmarshal(m, b)
-}
-func (m *NewFileTransfer) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
-	return xxx_messageInfo_NewFileTransfer.Marshal(b, m, deterministic)
+func (x *NewFileTransfer) String() string {
+	return protoimpl.X.MessageStringOf(x)
 }
-func (m *NewFileTransfer) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_NewFileTransfer.Merge(m, src)
-}
-func (m *NewFileTransfer) XXX_Size() int {
-	return xxx_messageInfo_NewFileTransfer.Size(m)
+
+func (*NewFileTransfer) ProtoMessage() {}
+
+func (x *NewFileTransfer) ProtoReflect() protoreflect.Message {
+	mi := &file_fileTransfer_ftMessages_proto_msgTypes[0]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
 }
-func (m *NewFileTransfer) XXX_DiscardUnknown() {
-	xxx_messageInfo_NewFileTransfer.DiscardUnknown(m)
+
+// Deprecated: Use NewFileTransfer.ProtoReflect.Descriptor instead.
+func (*NewFileTransfer) Descriptor() ([]byte, []int) {
+	return file_fileTransfer_ftMessages_proto_rawDescGZIP(), []int{0}
 }
 
-var xxx_messageInfo_NewFileTransfer proto.InternalMessageInfo
+func (x *NewFileTransfer) GetFileName() string {
+	if x != nil {
+		return x.FileName
+	}
+	return ""
+}
 
-func (m *NewFileTransfer) GetFileName() string {
-	if m != nil {
-		return m.FileName
+func (x *NewFileTransfer) GetFileType() string {
+	if x != nil {
+		return x.FileType
 	}
 	return ""
 }
 
-func (m *NewFileTransfer) GetTransferKey() []byte {
-	if m != nil {
-		return m.TransferKey
+func (x *NewFileTransfer) GetTransferKey() []byte {
+	if x != nil {
+		return x.TransferKey
 	}
 	return nil
 }
 
-func (m *NewFileTransfer) GetTransferMac() []byte {
-	if m != nil {
-		return m.TransferMac
+func (x *NewFileTransfer) GetTransferMac() []byte {
+	if x != nil {
+		return x.TransferMac
 	}
 	return nil
 }
 
-func (m *NewFileTransfer) GetNumParts() uint32 {
-	if m != nil {
-		return m.NumParts
+func (x *NewFileTransfer) GetNumParts() uint32 {
+	if x != nil {
+		return x.NumParts
 	}
 	return 0
 }
 
-func (m *NewFileTransfer) GetSize() uint32 {
-	if m != nil {
-		return m.Size
+func (x *NewFileTransfer) GetSize() uint32 {
+	if x != nil {
+		return x.Size
 	}
 	return 0
 }
 
-func (m *NewFileTransfer) GetRetry() float32 {
-	if m != nil {
-		return m.Retry
+func (x *NewFileTransfer) GetRetry() float32 {
+	if x != nil {
+		return x.Retry
 	}
 	return 0
 }
 
-func (m *NewFileTransfer) GetPreview() []byte {
-	if m != nil {
-		return m.Preview
+func (x *NewFileTransfer) GetPreview() []byte {
+	if x != nil {
+		return x.Preview
 	}
 	return nil
 }
 
-func init() {
-	proto.RegisterType((*NewFileTransfer)(nil), "parse.NewFileTransfer")
+var File_fileTransfer_ftMessages_proto protoreflect.FileDescriptor
+
+var file_fileTransfer_ftMessages_proto_rawDesc = []byte{
+	0x0a, 0x1d, 0x66, 0x69, 0x6c, 0x65, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x2f, 0x66,
+	0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12,
+	0x05, 0x70, 0x61, 0x72, 0x73, 0x65, 0x22, 0xed, 0x01, 0x0a, 0x0f, 0x4e, 0x65, 0x77, 0x46, 0x69,
+	0x6c, 0x65, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x66, 0x69,
+	0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x66, 0x69,
+	0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x54, 0x79,
+	0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x54, 0x79,
+	0x70, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x4b, 0x65,
+	0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65,
+	0x72, 0x4b, 0x65, 0x79, 0x12, 0x20, 0x0a, 0x0b, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72,
+	0x4d, 0x61, 0x63, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x74, 0x72, 0x61, 0x6e, 0x73,
+	0x66, 0x65, 0x72, 0x4d, 0x61, 0x63, 0x12, 0x1a, 0x0a, 0x08, 0x6e, 0x75, 0x6d, 0x50, 0x61, 0x72,
+	0x74, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x6e, 0x75, 0x6d, 0x50, 0x61, 0x72,
+	0x74, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0d,
+	0x52, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x72, 0x65, 0x74, 0x72, 0x79, 0x18,
+	0x07, 0x20, 0x01, 0x28, 0x02, 0x52, 0x05, 0x72, 0x65, 0x74, 0x72, 0x79, 0x12, 0x18, 0x0a, 0x07,
+	0x70, 0x72, 0x65, 0x76, 0x69, 0x65, 0x77, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x70,
+	0x72, 0x65, 0x76, 0x69, 0x65, 0x77, 0x42, 0x0f, 0x5a, 0x0d, 0x66, 0x69, 0x6c, 0x65, 0x54, 0x72,
+	0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x2f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+}
+
+var (
+	file_fileTransfer_ftMessages_proto_rawDescOnce sync.Once
+	file_fileTransfer_ftMessages_proto_rawDescData = file_fileTransfer_ftMessages_proto_rawDesc
+)
+
+func file_fileTransfer_ftMessages_proto_rawDescGZIP() []byte {
+	file_fileTransfer_ftMessages_proto_rawDescOnce.Do(func() {
+		file_fileTransfer_ftMessages_proto_rawDescData = protoimpl.X.CompressGZIP(file_fileTransfer_ftMessages_proto_rawDescData)
+	})
+	return file_fileTransfer_ftMessages_proto_rawDescData
 }
 
-func init() { proto.RegisterFile("fileTransfer/ftMessages.proto", fileDescriptor_9d574f363dd34365) }
+var file_fileTransfer_ftMessages_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
+var file_fileTransfer_ftMessages_proto_goTypes = []interface{}{
+	(*NewFileTransfer)(nil), // 0: parse.NewFileTransfer
+}
+var file_fileTransfer_ftMessages_proto_depIdxs = []int32{
+	0, // [0:0] is the sub-list for method output_type
+	0, // [0:0] is the sub-list for method input_type
+	0, // [0:0] is the sub-list for extension type_name
+	0, // [0:0] is the sub-list for extension extendee
+	0, // [0:0] is the sub-list for field type_name
+}
 
-var fileDescriptor_9d574f363dd34365 = []byte{
-	// 202 bytes of a gzipped FileDescriptorProto
-	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x4d, 0xcb, 0xcc, 0x49,
-	0x0d, 0x29, 0x4a, 0xcc, 0x2b, 0x4e, 0x4b, 0x2d, 0xd2, 0x4f, 0x2b, 0xf1, 0x4d, 0x2d, 0x2e, 0x4e,
-	0x4c, 0x4f, 0x2d, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x2d, 0x48, 0x2c, 0x2a, 0x4e,
-	0x55, 0xba, 0xc8, 0xc8, 0xc5, 0xef, 0x97, 0x5a, 0xee, 0x86, 0xa4, 0x56, 0x48, 0x8a, 0x8b, 0x03,
-	0xa4, 0xd7, 0x2f, 0x31, 0x37, 0x55, 0x82, 0x51, 0x81, 0x51, 0x83, 0x33, 0x08, 0xce, 0x17, 0x52,
-	0xe0, 0xe2, 0x2e, 0x81, 0xaa, 0xf3, 0x4e, 0xad, 0x94, 0x60, 0x52, 0x60, 0xd4, 0xe0, 0x09, 0x42,
-	0x16, 0x42, 0x56, 0xe1, 0x9b, 0x98, 0x2c, 0xc1, 0x8c, 0xaa, 0xc2, 0x37, 0x31, 0x19, 0x64, 0x7e,
-	0x5e, 0x69, 0x6e, 0x40, 0x62, 0x51, 0x49, 0xb1, 0x04, 0x8b, 0x02, 0xa3, 0x06, 0x6f, 0x10, 0x9c,
-	0x2f, 0x24, 0xc4, 0xc5, 0x52, 0x9c, 0x59, 0x95, 0x2a, 0xc1, 0x0a, 0x16, 0x07, 0xb3, 0x85, 0x44,
-	0xb8, 0x58, 0x8b, 0x52, 0x4b, 0x8a, 0x2a, 0x25, 0xd8, 0x14, 0x18, 0x35, 0x98, 0x82, 0x20, 0x1c,
-	0x21, 0x09, 0x2e, 0xf6, 0x82, 0xa2, 0xd4, 0xb2, 0xcc, 0xd4, 0x72, 0x09, 0x76, 0xb0, 0x1d, 0x30,
-	0xae, 0x13, 0x5f, 0x14, 0x0f, 0xb2, 0xdf, 0x93, 0xd8, 0xc0, 0x3e, 0x36, 0x06, 0x04, 0x00, 0x00,
-	0xff, 0xff, 0x3e, 0x0f, 0x1c, 0x27, 0x12, 0x01, 0x00, 0x00,
+func init() { file_fileTransfer_ftMessages_proto_init() }
+func file_fileTransfer_ftMessages_proto_init() {
+	if File_fileTransfer_ftMessages_proto != nil {
+		return
+	}
+	if !protoimpl.UnsafeEnabled {
+		file_fileTransfer_ftMessages_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*NewFileTransfer); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+	}
+	type x struct{}
+	out := protoimpl.TypeBuilder{
+		File: protoimpl.DescBuilder{
+			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+			RawDescriptor: file_fileTransfer_ftMessages_proto_rawDesc,
+			NumEnums:      0,
+			NumMessages:   1,
+			NumExtensions: 0,
+			NumServices:   0,
+		},
+		GoTypes:           file_fileTransfer_ftMessages_proto_goTypes,
+		DependencyIndexes: file_fileTransfer_ftMessages_proto_depIdxs,
+		MessageInfos:      file_fileTransfer_ftMessages_proto_msgTypes,
+	}.Build()
+	File_fileTransfer_ftMessages_proto = out.File
+	file_fileTransfer_ftMessages_proto_rawDesc = nil
+	file_fileTransfer_ftMessages_proto_goTypes = nil
+	file_fileTransfer_ftMessages_proto_depIdxs = nil
 }
diff --git a/fileTransfer/ftMessages.proto b/fileTransfer/ftMessages.proto
index e90449697bb5c9b3d9b4a40132b651aee6298d02..2802df2b580932c34651b9b43801cd4ae07abcf2 100644
--- a/fileTransfer/ftMessages.proto
+++ b/fileTransfer/ftMessages.proto
@@ -8,14 +8,15 @@
 syntax = "proto3";
 
 package parse;
-option go_package = "fileTransfer";
+option go_package = "fileTransfer/";
 
 message NewFileTransfer {
-    string fileName    = 1; // Name of the file; max 32 characters
-    bytes transferKey  = 2; // 256 bit encryption key to identify the transfer
-    bytes transferMac  = 3; // 256 bit MAC of the entire file
-    uint32 numParts    = 4; // Number of file parts
-    uint32 size        = 5; // The size of the file; max of 4 mB
-    float retry        = 6; // Used to determine how many times to retry sending
-    bytes preview      = 7; // A preview of the file; max of 4 kB
+    string fileName    = 1; // Name of the file; max 48 characters
+    string fileType    = 2; // Type of file; max 8 characters
+    bytes transferKey  = 3; // 256 bit encryption key to identify the transfer
+    bytes transferMac  = 4; // 256 bit MAC of the entire file
+    uint32 numParts    = 5; // Number of file parts
+    uint32 size        = 6; // The size of the file; max of 4 mB
+    float retry        = 7; // Used to determine how many times to retry sending
+    bytes preview      = 8; // A preview of the file; max of 4 kB
 }
\ No newline at end of file
diff --git a/fileTransfer/manager.go b/fileTransfer/manager.go
index e99fc971b4c85c55ec00d918ca025ba280611e15..00dd39e0c629eddd411e3dae6a9082f27d661c05 100644
--- a/fileTransfer/manager.go
+++ b/fileTransfer/manager.go
@@ -28,8 +28,12 @@ const (
 	PreviewMaxSize = 4_000
 
 	// FileNameMaxLen is the maximum size, in bytes, for a file name. Currently,
-	// it is set to 32 bytes.
-	FileNameMaxLen = 32
+	// it is set to 48 bytes.
+	FileNameMaxLen = 48
+
+	// FileTypeMaxLen is the maximum size, in bytes, for a file type. Currently,
+	// it is set to 8 bytes.
+	FileTypeMaxLen = 8
 
 	// FileMaxSize is the maximum file size that can be transferred. Currently,
 	// it is set to 4 mB.
@@ -56,6 +60,7 @@ const (
 
 	// Manager.Send
 	fileNameSizeErr = "length of filename (%d) greater than max allowed length (%d)"
+	fileTypeSizeErr = "length of file type (%d) greater than max allowed length (%d)"
 	fileSizeErr     = "size of file (%d bytes) greater than max allowed size (%d bytes)"
 	previewSizeErr  = "size of preview (%d bytes) greater than max allowed size (%d bytes)"
 	getPartSizeErr  = "failed to get file part size: %+v"
@@ -214,9 +219,10 @@ func (m *Manager) startProcesses(newFtChan, filePartChan chan message.Receive) (
 // initial NewFileTransfer E2E message to the recipient to inform them of the
 // incoming file parts. It partitions the file, puts it into storage, and queues
 // each file for sending. Returns a unique ID identifying the file transfer.
-func (m Manager) Send(fileName string, fileData []byte, recipient *id.ID,
-	retry float32, preview []byte, progressCB interfaces.SentProgressCallback,
-	period time.Duration) (ftCrypto.TransferID, error) {
+func (m Manager) Send(fileName, fileType string, fileData []byte,
+	recipient *id.ID, retry float32, preview []byte,
+	progressCB interfaces.SentProgressCallback, period time.Duration) (
+	ftCrypto.TransferID, error) {
 
 	// Return an error if the file name is too long
 	if len(fileName) > FileNameMaxLen {
@@ -224,6 +230,12 @@ func (m Manager) Send(fileName string, fileData []byte, recipient *id.ID,
 			fileNameSizeErr, len(fileName), FileNameMaxLen)
 	}
 
+	// Return an error if the file type is too long
+	if len(fileType) > FileTypeMaxLen {
+		return ftCrypto.TransferID{}, errors.Errorf(
+			fileTypeSizeErr, len(fileType), FileTypeMaxLen)
+	}
+
 	// Return an error if the file is too large
 	if len(fileData) > FileMaxSize {
 		return ftCrypto.TransferID{}, errors.Errorf(
@@ -260,8 +272,8 @@ func (m Manager) Send(fileName string, fileData []byte, recipient *id.ID,
 	fileSize := uint32(len(fileData))
 
 	// Send the initial file transfer message over E2E
-	err = m.sendNewFileTransfer(recipient, fileName, transferKey, mac, numParts,
-		fileSize, retry, preview)
+	err = m.sendNewFileTransfer(recipient, fileName, fileType, transferKey, mac,
+		numParts, fileSize, retry, preview)
 	if err != nil {
 		return ftCrypto.TransferID{}, errors.Errorf(sendInitMsgErr, err)
 	}
@@ -301,8 +313,10 @@ func (m Manager) RegisterSendProgressCallback(tid ftCrypto.TransferID,
 	return nil
 }
 
-// Resend resends a file if Send fails. Returns an error if CloseSend
-// was already called or if the transfer did not run out of retries.
+// Resend resends a file if sending fails. Returns an error if CloseSend
+// was already called or if the transfer did not run out of retries. This
+//function should only be called if the interfaces.SentProgressCallback returns
+//an error.
 // TODO: add test
 // TODO: write test
 // TODO: can you resend? Can you reuse fingerprints?
diff --git a/fileTransfer/manager_test.go b/fileTransfer/manager_test.go
index 4767dfa09d84f1e67f1dd8ffa6390c4f48385e22..de5f9d94840825fadff15972f5b5a52a3c54dee6 100644
--- a/fileTransfer/manager_test.go
+++ b/fileTransfer/manager_test.go
@@ -32,7 +32,7 @@ func Test_newManager(t *testing.T) {
 	kv := versioned.NewKV(make(ekv.Memstore))
 
 	cbChan := make(chan bool)
-	cb := func(ftCrypto.TransferID, string, *id.ID, uint32, []byte) {
+	cb := func(ftCrypto.TransferID, string, string, *id.ID, uint32, []byte) {
 		cbChan <- true
 	}
 
@@ -56,7 +56,7 @@ func Test_newManager(t *testing.T) {
 	}
 
 	// Check that the callback is called
-	go m.receiveCB(ftCrypto.TransferID{}, "", nil, 0, nil)
+	go m.receiveCB(ftCrypto.TransferID{}, "", "", nil, 0, nil)
 	select {
 	case <-cbChan:
 	case <-time.NewTimer(time.Millisecond).C:
@@ -71,6 +71,7 @@ func TestManager_Send(t *testing.T) {
 	prng := NewPrng(42)
 	recipient := id.NewIdFromString("recipient", id.User, t)
 	fileName := "testFile"
+	fileType := "txt"
 	numParts := uint16(16)
 	partSize, _ := m.getPartSize()
 	fileData, _ := newFile(numParts, uint32(partSize), prng, t)
@@ -78,7 +79,8 @@ func TestManager_Send(t *testing.T) {
 	retry := float32(1.5)
 	numFps := calcNumberOfFingerprints(numParts, retry)
 
-	tid, err := m.Send(fileName, fileData, recipient, retry, preview, nil, 0)
+	tid, err := m.Send(
+		fileName, fileType, fileData, recipient, retry, preview, nil, 0)
 	if err != nil {
 		t.Errorf("Send returned an error: %+v", err)
 	}
@@ -123,6 +125,7 @@ func TestManager_Send(t *testing.T) {
 	}
 	expectedNFT := &NewFileTransfer{
 		FileName:    fileName,
+		FileType:    fileType,
 		TransferKey: transfer.GetTransferKey().Bytes(),
 		TransferMac: ftCrypto.CreateTransferMAC(fileData, transfer.GetTransferKey()),
 		NumParts:    uint32(numParts),
@@ -130,7 +133,7 @@ func TestManager_Send(t *testing.T) {
 		Retry:       retry,
 		Preview:     preview,
 	}
-	if !reflect.DeepEqual(expectedNFT, receivedNFT) {
+	if !proto.Equal(expectedNFT, receivedNFT) {
 		t.Errorf("Received NewFileTransfer message does not match expected."+
 			"\nexpected: %+v\nreceived: %+v", expectedNFT, receivedNFT)
 	}
@@ -152,13 +155,28 @@ func TestManager_Send_FileNameLengthError(t *testing.T) {
 	fileName := strings.Repeat("A", FileNameMaxLen+1)
 	expectedErr := fmt.Sprintf(fileNameSizeErr, len(fileName), FileNameMaxLen)
 
-	_, err := m.Send(fileName, nil, nil, 0, nil, nil, 0)
+	_, err := m.Send(fileName, "", nil, nil, 0, nil, nil, 0)
 	if err == nil || err.Error() != expectedErr {
 		t.Errorf("Send did not return the expected error when the file name "+
 			"is too long.\nexpected: %s\nreceived: %+v", expectedErr, err)
 	}
 }
 
+// Error path: tests that Manager.Send returns the expected error when the
+// provided file type is longer than FileTypeMaxLen.
+func TestManager_Send_FileTypeLengthError(t *testing.T) {
+	m := newTestManager(false, nil, nil, nil, t)
+
+	fileType := strings.Repeat("A", FileTypeMaxLen+1)
+	expectedErr := fmt.Sprintf(fileTypeSizeErr, len(fileType), FileTypeMaxLen)
+
+	_, err := m.Send("", fileType, nil, nil, 0, nil, nil, 0)
+	if err == nil || err.Error() != expectedErr {
+		t.Errorf("Send did not return the expected error when the file type "+
+			"is too long.\nexpected: %s\nreceived: %+v", expectedErr, err)
+	}
+}
+
 // Error path: tests that Manager.Send returns the expected error when the
 // provided file is larger than FileMaxSize.
 func TestManager_Send_FileSizeError(t *testing.T) {
@@ -167,7 +185,7 @@ func TestManager_Send_FileSizeError(t *testing.T) {
 	fileData := make([]byte, FileMaxSize+1)
 	expectedErr := fmt.Sprintf(fileSizeErr, len(fileData), FileMaxSize)
 
-	_, err := m.Send("", fileData, nil, 0, nil, nil, 0)
+	_, err := m.Send("", "", fileData, nil, 0, nil, nil, 0)
 	if err == nil || err.Error() != expectedErr {
 		t.Errorf("Send did not return the expected error when the file data "+
 			"is too large.\nexpected: %s\nreceived: %+v", expectedErr, err)
@@ -182,7 +200,7 @@ func TestManager_Send_PreviewSizeError(t *testing.T) {
 	previewData := make([]byte, PreviewMaxSize+1)
 	expectedErr := fmt.Sprintf(previewSizeErr, len(previewData), PreviewMaxSize)
 
-	_, err := m.Send("", nil, nil, 0, previewData, nil, 0)
+	_, err := m.Send("", "", nil, nil, 0, previewData, nil, 0)
 	if err == nil || err.Error() != expectedErr {
 		t.Errorf("Send did not return the expected error when the preview "+
 			"data is too large.\nexpected: %s\nreceived: %+v", expectedErr, err)
@@ -196,6 +214,7 @@ func TestManager_Send_SendE2eError(t *testing.T) {
 	prng := NewPrng(42)
 	recipient := id.NewIdFromString("recipient", id.User, t)
 	fileName := "testFile"
+	fileType := "bytes"
 	numParts := uint16(16)
 	partSize, _ := m.getPartSize()
 	fileData, _ := newFile(numParts, uint32(partSize), prng, t)
@@ -204,7 +223,8 @@ func TestManager_Send_SendE2eError(t *testing.T) {
 
 	expectedErr := fmt.Sprintf(sendE2eErr, recipient, "")
 
-	_, err := m.Send(fileName, fileData, recipient, retry, preview, nil, 0)
+	_, err := m.Send(
+		fileName, fileType, fileData, recipient, retry, preview, nil, 0)
 	if err == nil || !strings.Contains(err.Error(), expectedErr) {
 		t.Errorf("Send did not return the expected error when the E2E message "+
 			"failed to send.\nexpected: %s\nreceived: %+v", expectedErr, err)
@@ -528,9 +548,10 @@ func Test_FileTransfer(t *testing.T) {
 
 	// Create callback with channel for receiving new file transfer
 	receiveNewCbChan := make(chan receivedFtResults, 100)
-	receiveNewCB := func(tid ftCrypto.TransferID, fileName string,
+	receiveNewCB := func(tid ftCrypto.TransferID, fileName, fileType string,
 		sender *id.ID, size uint32, preview []byte) {
-		receiveNewCbChan <- receivedFtResults{tid, fileName, sender, size, preview}
+		receiveNewCbChan <- receivedFtResults{
+			tid, fileName, fileType, sender, size, preview}
 	}
 
 	// Create reception channels for both managers
@@ -580,13 +601,14 @@ func Test_FileTransfer(t *testing.T) {
 	prng := NewPrng(42)
 	partSize, _ := m1.getPartSize()
 	fileName := "testFile"
+	fileType := "file"
 	file, parts := newFile(32, uint32(partSize), prng, t)
 	preview := parts[0]
 	recipient := id.NewIdFromString("recipient", id.User, t)
 
 	// Send file
-	sendTid, err := m1.Send(
-		fileName, file, recipient, 0.5, preview, sentCb, time.Millisecond)
+	sendTid, err := m1.Send(fileName, fileType, file, recipient, 0.5, preview,
+		sentCb, time.Millisecond)
 	if err != nil {
 		t.Errorf("Send returned an error: %+v", err)
 	}
diff --git a/fileTransfer/receiveNew.go b/fileTransfer/receiveNew.go
index 908eb0e7777ee24e1b7e3b46cf4e066b4d590ff1..2fa736cbbd2f7bd287095d4a8bfcd168f5d30707 100644
--- a/fileTransfer/receiveNew.go
+++ b/fileTransfer/receiveNew.go
@@ -39,7 +39,7 @@ func (m *Manager) receiveNewFileTransfer(rawMsgs chan message.Receive,
 		case receivedMsg := <-rawMsgs:
 			jww.DEBUG.Print("New file transfer message thread received message.")
 
-			tid, fileName, sender, size, preview, err :=
+			tid, fileName, fileType, sender, size, preview, err :=
 				m.readNewFileTransferMessage(receivedMsg)
 			if err != nil {
 				if err.Error() == receiveMessageTypeErr {
@@ -53,7 +53,7 @@ func (m *Manager) receiveNewFileTransfer(rawMsgs chan message.Receive,
 			}
 
 			// Call the reception callback
-			go m.receiveCB(tid, fileName, sender, size, preview)
+			go m.receiveCB(tid, fileName, fileType, sender, size, preview)
 
 			// Trigger a resend of all garbled messages
 			m.net.CheckGarbledMessages()
@@ -65,20 +65,21 @@ func (m *Manager) receiveNewFileTransfer(rawMsgs chan message.Receive,
 // received transfer list. Returns the transfer ID, sender ID, file size, and
 // file preview.
 func (m *Manager) readNewFileTransferMessage(msg message.Receive) (
-	ftCrypto.TransferID, string, *id.ID, uint32, []byte, error) {
+	tid ftCrypto.TransferID, fileName, fileType string, sender *id.ID,
+	fileSize uint32, preview []byte, err error) {
 
 	// Return an error if the message is not a NewFileTransfer
 	if msg.MessageType != message.NewFileTransfer {
-		return ftCrypto.TransferID{}, "", nil, 0, nil,
-			errors.New(receiveMessageTypeErr)
+		err = errors.New(receiveMessageTypeErr)
+		return
 	}
 
 	// Unmarshal the request message
 	newFT := &NewFileTransfer{}
-	err := proto.Unmarshal(msg.Payload, newFT)
+	err = proto.Unmarshal(msg.Payload, newFT)
 	if err != nil {
-		return ftCrypto.TransferID{}, "", nil, 0, nil,
-			errors.Errorf(protoUnmarshalErr, err)
+		err = errors.Errorf(protoUnmarshalErr, err)
+		return
 	}
 
 	// Get RNG from stream
@@ -89,11 +90,12 @@ func (m *Manager) readNewFileTransferMessage(msg message.Receive) (
 	key := ftCrypto.UnmarshalTransferKey(newFT.TransferKey)
 	numParts := uint16(newFT.NumParts)
 	numFps := calcNumberOfFingerprints(numParts, newFT.Retry)
-	tid, err := m.received.AddTransfer(
+	tid, err = m.received.AddTransfer(
 		key, newFT.TransferMac, newFT.Size, numParts, numFps, rng)
 	if err != nil {
-		return ftCrypto.TransferID{}, "", nil, 0, nil, err
+		return
 	}
 
-	return tid, newFT.FileName, msg.Sender, newFT.Size, newFT.Preview, nil
+	return tid, newFT.FileName, newFT.FileType, msg.Sender, newFT.Size,
+		newFT.Preview, nil
 }
diff --git a/fileTransfer/receiveNew_test.go b/fileTransfer/receiveNew_test.go
index 16863e80e7a8bdbdcb5b640b77daa6840e253251..5bbfe8e523b7fb6c5ba0ddd840416f5e4a4c42f1 100644
--- a/fileTransfer/receiveNew_test.go
+++ b/fileTransfer/receiveNew_test.go
@@ -24,9 +24,10 @@ import (
 func TestManager_receiveNewFileTransfer(t *testing.T) {
 	// Create new ReceiveCallback that sends the results on a channel
 	receiveChan := make(chan receivedFtResults)
-	receiveCB := func(tid ftCrypto.TransferID, fileName string, sender *id.ID,
-		size uint32, preview []byte) {
-		receiveChan <- receivedFtResults{tid, fileName, sender, size, preview}
+	receiveCB := func(tid ftCrypto.TransferID, fileName, fileType string,
+		sender *id.ID, size uint32, preview []byte) {
+		receiveChan <- receivedFtResults{
+			tid, fileName, fileType, sender, size, preview}
 	}
 
 	// Create new manager, stoppable, and channel to receive messages
@@ -92,9 +93,10 @@ func TestManager_receiveNewFileTransfer(t *testing.T) {
 func TestManager_receiveNewFileTransfer_Stop(t *testing.T) {
 	// Create new ReceiveCallback that sends the results on a channel
 	receiveChan := make(chan receivedFtResults)
-	receiveCB := func(tid ftCrypto.TransferID, fileName string, sender *id.ID,
-		size uint32, preview []byte) {
-		receiveChan <- receivedFtResults{tid, fileName, sender, size, preview}
+	receiveCB := func(tid ftCrypto.TransferID, fileName, fileType string,
+		sender *id.ID, size uint32, preview []byte) {
+		receiveChan <- receivedFtResults{
+			tid, fileName, fileType, sender, size, preview}
 	}
 
 	// Create new manager, stoppable, and channel to receive messages
@@ -152,9 +154,10 @@ func TestManager_receiveNewFileTransfer_Stop(t *testing.T) {
 func TestManager_receiveNewFileTransfer_InvalidMessageError(t *testing.T) {
 	// Create new ReceiveCallback that sends the results on a channel
 	receiveChan := make(chan receivedFtResults)
-	receiveCB := func(tid ftCrypto.TransferID, fileName string, sender *id.ID,
-		size uint32, preview []byte) {
-		receiveChan <- receivedFtResults{tid, fileName, sender, size, preview}
+	receiveCB := func(tid ftCrypto.TransferID, fileName, fileType string,
+		sender *id.ID, size uint32, preview []byte) {
+		receiveChan <- receivedFtResults{
+			tid, fileName, fileType, sender, size, preview}
 	}
 
 	// Create new manager, stoppable, and channel to receive messages
@@ -196,12 +199,14 @@ func TestManager_readNewFileTransferMessage(t *testing.T) {
 	// Create new message.Send containing marshalled NewFileTransfer
 	recipient := id.NewIdFromString("recipient", id.User, t)
 	expectedFileName := "testFile"
+	expectedFileType := "txt"
 	key, _ := ftCrypto.NewTransferKey(NewPrng(42))
 	mac := []byte("transferMac")
 	numParts, expectedFileSize, retry := uint16(16), uint32(256), float32(1.5)
 	expectedPreview := []byte("filePreview")
-	sendMsg, err := newNewFileTransferE2eMessage(recipient, expectedFileName,
-		key, mac, numParts, expectedFileSize, retry, expectedPreview)
+	sendMsg, err := newNewFileTransferE2eMessage(
+		recipient, expectedFileName, expectedFileType, key, mac, numParts,
+		expectedFileSize, retry, expectedPreview)
 	if err != nil {
 		t.Errorf("Failed to create new Send message: %+v", err)
 	}
@@ -214,7 +219,8 @@ func TestManager_readNewFileTransferMessage(t *testing.T) {
 	}
 
 	// Read the message
-	_, fileName, sender, fileSize, preview, err := m.readNewFileTransferMessage(receiveMsg)
+	_, fileName, fileType, sender, fileSize, preview, err :=
+		m.readNewFileTransferMessage(receiveMsg)
 	if err != nil {
 		t.Errorf("readNewFileTransferMessage returned an error: %+v", err)
 	}
@@ -224,6 +230,11 @@ func TestManager_readNewFileTransferMessage(t *testing.T) {
 			"\nexpected: %q\nreceived: %q", expectedFileName, fileName)
 	}
 
+	if expectedFileType != fileType {
+		t.Errorf("Returned file type does not match expected."+
+			"\nexpected: %q\nreceived: %q", expectedFileType, fileType)
+	}
+
 	if !receiveMsg.Sender.Cmp(sender) {
 		t.Errorf("Returned sender ID does not match expected."+
 			"\nexpected: %s\nreceived: %s", receiveMsg.Sender, sender)
@@ -252,7 +263,7 @@ func TestManager_readNewFileTransferMessage_MessageTypeError(t *testing.T) {
 	}
 
 	// Read the message
-	_, _, _, _, _, err := m.readNewFileTransferMessage(receiveMsg)
+	_, _, _, _, _, _, err := m.readNewFileTransferMessage(receiveMsg)
 	if err == nil || err.Error() != expectedErr {
 		t.Errorf("readNewFileTransferMessage did not return the expected "+
 			"error when the message.Receive has the wrong MessageType."+
@@ -274,7 +285,7 @@ func TestManager_readNewFileTransferMessage_ProtoUnmarshalError(t *testing.T) {
 	}
 
 	// Read the message
-	_, _, _, _, _, err := m.readNewFileTransferMessage(receiveMsg)
+	_, _, _, _, _, _, err := m.readNewFileTransferMessage(receiveMsg)
 	if err == nil || !strings.Contains(err.Error(), expectedErr) {
 		t.Errorf("readNewFileTransferMessage did not return the expected "+
 			"error when the payload could not be unmarshalled."+
diff --git a/fileTransfer/sendNew.go b/fileTransfer/sendNew.go
index 22282ea6a0a2547c7eff8c83f0ec79e4e3e8699c..1513453c3af06c0affe40ba9a616b1d8fb4ce800 100644
--- a/fileTransfer/sendNew.go
+++ b/fileTransfer/sendNew.go
@@ -23,13 +23,13 @@ const (
 )
 
 // sendNewFileTransfer sends the initial file transfer message over E2E.
-func (m *Manager) sendNewFileTransfer(recipient *id.ID, fileName string,
-	key ftCrypto.TransferKey, mac []byte, numParts uint16, fileSize uint32,
-	retry float32, preview []byte) error {
+func (m *Manager) sendNewFileTransfer(recipient *id.ID, fileName,
+	fileType string, key ftCrypto.TransferKey, mac []byte, numParts uint16,
+	fileSize uint32, retry float32, preview []byte) error {
 
 	// Create Send message with marshalled NewFileTransfer
-	sendMsg, err := newNewFileTransferE2eMessage(recipient, fileName, key, mac,
-		numParts, fileSize, retry, preview)
+	sendMsg, err := newNewFileTransferE2eMessage(recipient, fileName, fileType,
+		key, mac, numParts, fileSize, retry, preview)
 	if err != nil {
 		return errors.Errorf(protoMarshalErr, err)
 	}
@@ -45,13 +45,14 @@ func (m *Manager) sendNewFileTransfer(recipient *id.ID, fileName string,
 
 // newNewFileTransferE2eMessage generates the message.Send for the given
 // recipient containing the marshalled NewFileTransfer message.
-func newNewFileTransferE2eMessage(recipient *id.ID, fileName string,
+func newNewFileTransferE2eMessage(recipient *id.ID, fileName, fileType string,
 	key ftCrypto.TransferKey, mac []byte, numParts uint16, fileSize uint32,
 	retry float32, preview []byte) (message.Send, error) {
 
 	// Construct NewFileTransfer message
 	protoMsg := &NewFileTransfer{
 		FileName:    fileName,
+		FileType:    fileType,
 		TransferKey: key.Bytes(),
 		TransferMac: mac,
 		NumParts:    uint32(numParts),
diff --git a/fileTransfer/sendNew_test.go b/fileTransfer/sendNew_test.go
index 54342a84e84bedfe30877e101dbf3193200422a4..53adcb934d8dbf3d544087a27ad5780c35f631ad 100644
--- a/fileTransfer/sendNew_test.go
+++ b/fileTransfer/sendNew_test.go
@@ -25,19 +25,20 @@ func TestManager_sendNewFileTransfer(t *testing.T) {
 
 	recipient := id.NewIdFromString("recipient", id.User, t)
 	fileName := "testFile"
+	fileType := "txt"
 	key, _ := ftCrypto.NewTransferKey(NewPrng(42))
 	mac := []byte("transferMac")
 	numParts, fileSize, retry := uint16(16), uint32(256), float32(1.5)
 	preview := []byte("filePreview")
 
-	expected, err := newNewFileTransferE2eMessage(recipient, fileName, key, mac,
-		numParts, fileSize, retry, preview)
+	expected, err := newNewFileTransferE2eMessage(recipient, fileName, fileType,
+		key, mac, numParts, fileSize, retry, preview)
 	if err != nil {
 		t.Errorf("Failed to create new Send message: %+v", err)
 	}
 
-	err = m.sendNewFileTransfer(recipient, fileName, key, mac, numParts,
-		fileSize, retry, preview)
+	err = m.sendNewFileTransfer(recipient, fileName, fileType, key, mac,
+		numParts, fileSize, retry, preview)
 	if err != nil {
 		t.Errorf("sendNewFileTransfer returned an error: %+v", err)
 	}
@@ -60,7 +61,7 @@ func TestManager_sendNewFileTransfer_E2eError(t *testing.T) {
 	key, _ := ftCrypto.NewTransferKey(NewPrng(42))
 
 	expectedErr := fmt.Sprintf(sendE2eErr, recipient, "")
-	err := m.sendNewFileTransfer(recipient, "", key, nil, 16, 256, 1.5, nil)
+	err := m.sendNewFileTransfer(recipient, "", "", key, nil, 16, 256, 1.5, nil)
 	if err == nil || !strings.Contains(err.Error(), expectedErr) {
 		t.Errorf("sendNewFileTransfer di dnot return the expected error when "+
 			"SendE2E failed.\nexpected: %s\nreceived: %+v", expectedErr, err)
@@ -80,6 +81,7 @@ func Test_newNewFileTransferE2eMessage(t *testing.T) {
 	key, _ := ftCrypto.NewTransferKey(NewPrng(42))
 	expected := &NewFileTransfer{
 		FileName:    "testFile",
+		FileType:    "txt",
 		TransferKey: key.Bytes(),
 		TransferMac: []byte("transferMac"),
 		NumParts:    16,
@@ -89,8 +91,8 @@ func Test_newNewFileTransferE2eMessage(t *testing.T) {
 	}
 
 	sendMsg, err := newNewFileTransferE2eMessage(recipient, expected.FileName,
-		key, expected.TransferMac, uint16(expected.NumParts), expected.Size,
-		expected.Retry, expected.Preview)
+		expected.FileType, key, expected.TransferMac, uint16(expected.NumParts),
+		expected.Size, expected.Retry, expected.Preview)
 	if err != nil {
 		t.Errorf("newNewFileTransferE2eMessage returned an error: %+v", err)
 	}
@@ -112,7 +114,7 @@ func Test_newNewFileTransferE2eMessage(t *testing.T) {
 		t.Errorf("Failed to unmarshal received NewFileTransfer: %+v", err)
 	}
 
-	if !reflect.DeepEqual(expected, received) {
+	if !proto.Equal(expected, received) {
 		t.Errorf("Received NewFileTransfer does not match expected."+
 			"\nexpected: %+v\nreceived: %+v", expected, received)
 	}
diff --git a/fileTransfer/utils_test.go b/fileTransfer/utils_test.go
index e0a0fa6f00c12004a90baeba5c0e20b437e0d9a1..d31e7f9ce306f99064e2916e28461d317a120e0f 100644
--- a/fileTransfer/utils_test.go
+++ b/fileTransfer/utils_test.go
@@ -287,6 +287,7 @@ func newTestManagerWithTransfers(numParts []uint16, sendErr bool,
 type receivedFtResults struct {
 	tid      ftCrypto.TransferID
 	fileName string
+	fileType string
 	sender   *id.ID
 	size     uint32
 	preview  []byte
diff --git a/interfaces/fileTransfer.go b/interfaces/fileTransfer.go
index 3f1c888af925a9603434ecadcf0a8c5fdab29ae7..382ab098b97164da09a44e6cc09ee765ab2fad40 100644
--- a/interfaces/fileTransfer.go
+++ b/interfaces/fileTransfer.go
@@ -25,7 +25,7 @@ type ReceivedProgressCallback func(completed bool, received, total uint16,
 
 // ReceiveCallback is a callback function that notifies the receiver of an
 // incoming file transfer.
-type ReceiveCallback func(tid ftCrypto.TransferID, fileName string,
+type ReceiveCallback func(tid ftCrypto.TransferID, fileName, fileType string,
 	sender *id.ID, size uint32, preview []byte)
 
 // FileTransfer facilities the sending and receiving of large file transfers.
@@ -39,9 +39,9 @@ type FileTransfer interface {
 	// The preview stores a preview of the data (such as a thumbnail) and is
 	// capped at 4 kB in size.
 	// Returns a unique transfer ID used to identify the transfer.
-	Send(fileName string, fileData []byte, recipient *id.ID, retry float32,
-		preview []byte, progressCB SentProgressCallback, period time.Duration) (
-		ftCrypto.TransferID, error)
+	Send(fileName, fileType string, fileData []byte, recipient *id.ID,
+		retry float32, preview []byte, progressCB SentProgressCallback,
+		period time.Duration) (ftCrypto.TransferID, error)
 
 	// RegisterSendProgressCallback allows for the registration of a callback to
 	// track the progress of an individual sent file transfer. The callback will
@@ -54,7 +54,7 @@ type FileTransfer interface {
 	RegisterSendProgressCallback(tid ftCrypto.TransferID,
 		progressCB SentProgressCallback, period time.Duration) error
 
-	// Resend resends a file if Send fails. Returns an error if CloseSend
+	// Resend resends a file if sending fails. Returns an error if CloseSend
 	// was already called or if the transfer did not run out of retries.
 	Resend(tid ftCrypto.TransferID) error