diff --git a/pom.xml b/pom.xml
index d7fdd2a3f9f550d3ca4c7fa093eccb2d53c6df03..0130dea34cb3a0f7b1db4a66ea7785cb45546774 100644
--- a/pom.xml
+++ b/pom.xml
@@ -19,7 +19,7 @@
 	<properties>
 		<api-lib.version>0.16.0</api-lib.version>
 		<nachrichten-manager.version>2.17.0-SNAPSHOT</nachrichten-manager.version>
-		<openapi-generator.version>7.10.0</openapi-generator.version>
+		<openapi-generator.version>7.11.0</openapi-generator.version>
 		<swagger-parser.version>2.1.23</swagger-parser.version>
 		<wiremock-spring-boot.version>3.6.0</wiremock-spring-boot.version>
 	</properties>
@@ -40,6 +40,10 @@
 			<groupId>org.springframework.boot</groupId>
 			<artifactId>spring-boot-starter-validation</artifactId>
 		</dependency>
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter-data-mongodb</artifactId>
+		</dependency>
 		<dependency>
 			<groupId>org.springframework.boot</groupId>
 			<artifactId>spring-boot-starter-oauth2-client</artifactId>
@@ -139,7 +143,10 @@
 						<configuration>
 							<inputSpec>${project.basedir}/spec/postfach-api-facade.yaml</inputSpec>
 							<generatorName>java</generatorName>
+							<generateModelTests>false</generateModelTests>
+							<generateApiTests>false</generateApiTests>
 							<configOptions>
+								<!-- https://openapi-generator.tech/docs/generators/java/#config-options -->
 								<sourceFolder>src/gen/java/main</sourceFolder>
 								<serializationLibrary>jackson</serializationLibrary>
 								<library>restclient</library>
@@ -147,6 +154,8 @@
 								<apiPackage>de.ozgcloud.nachrichten.postfach.osiv2.gen.api</apiPackage>
 								<modelPackage>de.ozgcloud.nachrichten.postfach.osiv2.gen.model</modelPackage>
 								<openApiNullable>false</openApiNullable>
+								<generateBuilders>true</generateBuilders>
+								<useAbstractionForFiles>true</useAbstractionForFiles>
 							</configOptions>
 						</configuration>
 					</execution>
diff --git a/spec/postfach-api-facade.yaml b/spec/postfach-api-facade.yaml
index 0414d95e73a7a704396be50ed764b23684c96efe..9a67d1cbd7ec9a71af0f96dfbc0512d6a5abd6aa 100644
--- a/spec/postfach-api-facade.yaml
+++ b/spec/postfach-api-facade.yaml
@@ -844,7 +844,7 @@ paths:
                 detail: Der Dienst ist zurzeit nicht verfügbar.
   /MessageExchange/v1/Send/{mailboxId}:
     post:
-      operationId: SendMessage
+      operationId: sendMessage
       tags:
       - MessageExchange
       summary: Sendet eine Nachricht an ein externes oder internes Postfach.
@@ -1733,6 +1733,7 @@ paths:
           description: OK
   /Quarantine/v1/Upload/{guid}:
     get:
+      operationId: getUploadStatus
       tags:
       - Quarantine
       summary: Liefert den Status der Virenprüfung.
@@ -1819,6 +1820,7 @@ paths:
                 status: 503
                 detail: Der Dienst ist zurzeit nicht verfügbar.
     delete:
+      operationId: deleteUpload
       tags:
       - Quarantine
       summary: Markiert die Datei zum Löschen
@@ -1905,6 +1907,7 @@ paths:
                 detail: Der Dienst ist zurzeit nicht verfügbar.
   /Quarantine/v1/Upload/Chunked:
     post:
+      operationId: uploadChunk
       tags:
       - Quarantine
       summary: Lädt ein Dateistück in die Quarantäne hoch
diff --git a/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/OsiPostfachRemoteService.java b/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/OsiPostfachRemoteService.java
index 42c45db565ca8bb736d62827193e7d9c498bdbb4..e72a60c599aa61d2e0c47e27c1e24546b8670e3c 100644
--- a/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/OsiPostfachRemoteService.java
+++ b/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/OsiPostfachRemoteService.java
@@ -8,6 +8,7 @@ import org.springframework.stereotype.Service;
 import de.ozgcloud.nachrichten.postfach.PostfachNachricht;
 import de.ozgcloud.nachrichten.postfach.PostfachRemoteService;
 import de.ozgcloud.nachrichten.postfach.osiv2.config.Osi2PostfachProperties;
+import de.ozgcloud.nachrichten.postfach.osiv2.transfer.Osi2PostfachService;
 import de.ozgcloud.nachrichten.postfach.osiv2.transfer.PostfachApiFacadeService;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.log4j.Log4j2;
@@ -17,14 +18,14 @@ import lombok.extern.log4j.Log4j2;
 @Log4j2
 @RequiredArgsConstructor
 public class OsiPostfachRemoteService implements PostfachRemoteService {
-	private final PostfachApiFacadeService postfachApiFacadeService;
+	private final Osi2PostfachService osi2PostfachService;
 
 	public static final String POSTFACH_TYPE_OSI = "OSI";
 
 	@Override
 	public void sendMessage(PostfachNachricht nachricht) {
 		try {
-			postfachApiFacadeService.sendMessage(nachricht);
+			osi2PostfachService.sendMessage(nachricht);
 		} catch (RuntimeException e) {
 			throw new OsiPostfachException("Failed to send message", e);
 		}
@@ -33,7 +34,7 @@ public class OsiPostfachRemoteService implements PostfachRemoteService {
 	@Override
 	public Stream<PostfachNachricht> getAllMessages() {
 		try {
-			return postfachApiFacadeService.receiveMessages();
+			return osi2PostfachService.receiveMessages();
 		} catch (RuntimeException e) {
 			throw new OsiPostfachException("Failed to get messages", e);
 		}
@@ -42,7 +43,7 @@ public class OsiPostfachRemoteService implements PostfachRemoteService {
 	@Override
 	public void deleteMessage(String messageId) {
 		try {
-			postfachApiFacadeService.deleteMessage(messageId);
+			osi2PostfachService.deleteMessage(messageId);
 		} catch (RuntimeException e) {
 			throw new OsiPostfachException("Failed to delete message", e);
 		}
diff --git a/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/model/UploadFileMetadata.java b/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/model/UploadFileMetadata.java
new file mode 100644
index 0000000000000000000000000000000000000000..e1b6ead85e65860e4b15ad6798aaf37083658294
--- /dev/null
+++ b/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/model/UploadFileMetadata.java
@@ -0,0 +1,12 @@
+package de.ozgcloud.nachrichten.postfach.osiv2.model;
+
+import lombok.Builder;
+
+@Builder
+public record UploadFileMetadata(
+		String guid,
+		String name,
+		String contentType,
+		Long size
+) {
+}
diff --git a/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/transfer/Osi2PostfachService.java b/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/transfer/Osi2PostfachService.java
new file mode 100644
index 0000000000000000000000000000000000000000..372704e2de6dc99884053c3488d96604cb9fa9d7
--- /dev/null
+++ b/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/transfer/Osi2PostfachService.java
@@ -0,0 +1,38 @@
+package de.ozgcloud.nachrichten.postfach.osiv2.transfer;
+
+import java.util.stream.Stream;
+
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.stereotype.Service;
+
+import de.ozgcloud.nachrichten.postfach.PostfachNachricht;
+import de.ozgcloud.nachrichten.postfach.osiv2.config.Osi2PostfachProperties;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.log4j.Log4j2;
+
+@Log4j2
+@Service
+@ConditionalOnProperty(prefix = Osi2PostfachProperties.PREFIX, name = "enabled", havingValue = "true")
+@RequiredArgsConstructor
+public class Osi2PostfachService {
+	private final PostfachApiFacadeService postfachApiFacadeService;
+	private final Osi2QuarantineService quarantineService;
+
+	public void sendMessage(PostfachNachricht nachricht) {
+		postfachApiFacadeService.sendMessage(
+				nachricht,
+				quarantineService.uploadAttachments(nachricht.getAttachments())
+		);
+	}
+
+	public Stream<PostfachNachricht> receiveMessages() {
+		return postfachApiFacadeService.fetchPendingMessageIds()
+				.stream()
+				.map(postfachApiFacadeService::fetchMessageById);
+	}
+
+	public void deleteMessage(final String messageId) {
+		postfachApiFacadeService.deleteMessage(messageId);
+	}
+
+}
diff --git a/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/transfer/Osi2QuarantineService.java b/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/transfer/Osi2QuarantineService.java
new file mode 100644
index 0000000000000000000000000000000000000000..5f18c4d64a6634678adb3b6ff9b03f79f30a6080
--- /dev/null
+++ b/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/transfer/Osi2QuarantineService.java
@@ -0,0 +1,57 @@
+package de.ozgcloud.nachrichten.postfach.osiv2.transfer;
+
+import java.util.List;
+
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.stereotype.Service;
+
+import de.ozgcloud.nachrichten.postfach.osiv2.config.Osi2PostfachProperties;
+import de.ozgcloud.nachrichten.postfach.osiv2.model.UploadFileMetadata;
+import de.ozgcloud.vorgang.grpc.binaryFile.BinaryFileServiceGrpc;
+import de.ozgcloud.vorgang.grpc.binaryFile.GrpcGetBinaryFileDataRequest;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.log4j.Log4j2;
+
+@Log4j2
+@Service
+@ConditionalOnProperty(prefix = Osi2PostfachProperties.PREFIX, name = "enabled", havingValue = "true")
+@RequiredArgsConstructor
+public class Osi2QuarantineService {
+	private final PostfachApiFacadeService postfachApiFacadeService;
+	private final BinaryFileServiceGrpc.BinaryFileServiceBlockingStub binaryFileService;
+
+	public List<UploadFileMetadata> uploadAttachments(List<String> attachmentIds) {
+		var uploadFileMetadata = attachmentIds.stream()
+				.map(this::uploadFileByAttachmentId)
+				.toList();
+		waitForVirusScan(uploadFileMetadata);
+		return uploadFileMetadata;
+	}
+
+	void waitForVirusScan(List<UploadFileMetadata> uploadFileMetadata) {
+		// TODO
+	}
+
+	void checkVirusScanCompleted(List<UploadFileMetadata> uploadFileMetadata) {
+		// TODO
+	}
+
+	UploadFileMetadata uploadFileByAttachmentId(String attachmentId) {
+		// TODO
+		//		var request = createRequestWithFileId(attachmentId);
+		//		var metadata = binaryFileService.findBinaryFilesMetaData(GrpcBinaryFilesRequest.newBuilder().)
+		//		var content = binaryFileService.getBinaryFileContent(request);
+		//
+		//		content.next().getFileContent().writeTo();
+		return null;
+	}
+
+	private GrpcGetBinaryFileDataRequest createRequestWithFileId(String fileId) {
+		return GrpcGetBinaryFileDataRequest.newBuilder().setFileId(fileId).build();
+	}
+
+	public void deleteAttachments(List<UploadFileMetadata> uploadFileMetadata) {
+		// TODO delete on exception
+	}
+
+}
diff --git a/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/transfer/Osi2RequestMapper.java b/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/transfer/Osi2RequestMapper.java
index c2aab079e54ede89a9b32c09d5791e663283b71f..bf883afec4d1e4ad65c89198b3eb1c704bc48ed1 100644
--- a/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/transfer/Osi2RequestMapper.java
+++ b/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/transfer/Osi2RequestMapper.java
@@ -2,38 +2,47 @@ package de.ozgcloud.nachrichten.postfach.osiv2.transfer;
 
 import java.util.Collections;
 import java.util.List;
+import java.util.Objects;
 import java.util.Optional;
 
+import org.mapstruct.BeforeMapping;
+import org.mapstruct.Context;
 import org.mapstruct.Mapper;
 import org.mapstruct.Mapping;
+import org.mapstruct.Named;
 import org.mapstruct.ReportingPolicy;
 
 import de.ozgcloud.nachrichten.postfach.PostfachAddress;
 import de.ozgcloud.nachrichten.postfach.PostfachAddressIdentifier;
 import de.ozgcloud.nachrichten.postfach.PostfachNachricht;
+import de.ozgcloud.nachrichten.postfach.osiv2.gen.model.DomainChunkMetaData;
 import de.ozgcloud.nachrichten.postfach.osiv2.gen.model.MessageExchangeFiles;
 import de.ozgcloud.nachrichten.postfach.osiv2.gen.model.OutSendMessageRequestV2;
 import de.ozgcloud.nachrichten.postfach.osiv2.gen.model.V1References;
 import de.ozgcloud.nachrichten.postfach.osiv2.gen.model.V1ReplyBehavior;
+import de.ozgcloud.nachrichten.postfach.osiv2.model.UploadFileMetadata;
 
 @Mapper(unmappedTargetPolicy = ReportingPolicy.ERROR)
 public interface Osi2RequestMapper {
 
-	@Mapping(target = "sequencenumber", source = "vorgangId")
-	@Mapping(target = "body", source = "mailBody")
+	int MAX_NUMBER_RECEIVED_MESSAGES = 100;
+
+	@Mapping(target = "sequencenumber", source = "nachricht.vorgangId")
+	@Mapping(target = "body", source = "nachricht.mailBody")
 	@Mapping(target = "displayName", ignore = true)
 	@Mapping(target = "originSender", ignore = true)
-	@Mapping(target = "replyAction", source = "replyOption")
+	@Mapping(target = "replyAction", source = "nachricht.replyOption")
 	@Mapping(target = "eidasLevel", constant = "LOW")
 	@Mapping(target = "isObligatory", expression = "java( false )")
 	@Mapping(target = "isHtml", expression = "java( false )")
-	@Mapping(target = "files", expression = "java( mapMessageExchangeFiles() )")
+	@Mapping(target = "files", source = "files")
 	@Mapping(target = "references", expression = "java( mapReferences() )")
-	OutSendMessageRequestV2 mapOutSendMessageRequestV2(PostfachNachricht nachricht);
+	OutSendMessageRequestV2 mapOutSendMessageRequestV2(PostfachNachricht nachricht, List<UploadFileMetadata> files);
 
-	default List<MessageExchangeFiles> mapMessageExchangeFiles() {
-		return Collections.emptyList();
-	}
+
+	@Mapping(target = "mimeType", source = "contentType")
+	@Mapping(target = "isOriginalMessage", expression = "java( false )")
+	MessageExchangeFiles mapMessageExchangeFile(UploadFileMetadata attachmentMetadata);
 
 	default List<V1References> mapReferences() {
 		return Collections.emptyList();
@@ -47,6 +56,9 @@ public interface Osi2RequestMapper {
 		};
 	}
 
+
+	DomainChunkMetaData mapDomainChunkMetaData(UploadFileMetadata attachmentMetadata);
+
 	default String mapMailboxId(PostfachNachricht nachricht) {
 		return Optional.ofNullable(nachricht.getPostfachAddress())
 				.map(PostfachAddress::getIdentifier)
diff --git a/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/transfer/Osi2ResponseMapper.java b/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/transfer/Osi2ResponseMapper.java
index ef8d1ea7f2d5e9d28499e8f05badc783b0854fc5..fbd75f8856267849a83265f973917c6e2f0b28c8 100644
--- a/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/transfer/Osi2ResponseMapper.java
+++ b/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/transfer/Osi2ResponseMapper.java
@@ -2,6 +2,10 @@ package de.ozgcloud.nachrichten.postfach.osiv2.transfer;
 
 import java.time.OffsetDateTime;
 import java.time.ZonedDateTime;
+import java.util.Collection;
+import java.util.List;
+import java.util.Objects;
+import java.util.Optional;
 import java.util.UUID;
 
 import org.mapstruct.Mapper;
@@ -12,7 +16,10 @@ import org.mapstruct.ReportingPolicy;
 import de.ozgcloud.nachrichten.postfach.PostfachAddress;
 import de.ozgcloud.nachrichten.postfach.PostfachAddressIdentifier;
 import de.ozgcloud.nachrichten.postfach.PostfachNachricht;
+import de.ozgcloud.nachrichten.postfach.osiv2.OsiPostfachException;
 import de.ozgcloud.nachrichten.postfach.osiv2.OsiPostfachRemoteService;
+import de.ozgcloud.nachrichten.postfach.osiv2.gen.model.MessageExchangeReceiveMessage;
+import de.ozgcloud.nachrichten.postfach.osiv2.gen.model.MessageExchangeReceiveMessagesResponse;
 import de.ozgcloud.nachrichten.postfach.osiv2.gen.model.V1ReplyBehavior;
 import de.ozgcloud.nachrichten.postfach.osiv2.gen.model.V1ReplyMessage;
 import lombok.Builder;
@@ -86,6 +93,20 @@ public interface Osi2ResponseMapper {
 				};
 	}
 
+	default List<String> toMessageIds(MessageExchangeReceiveMessagesResponse response) {
+		if (response == null) {
+			throw new OsiPostfachException("Expect non empty response!", null);
+		}
+
+		return Optional.ofNullable(response.getMessages())
+				.stream()
+				.flatMap(Collection::stream)
+				.map(MessageExchangeReceiveMessage::getGuid)
+				.filter(Objects::nonNull)
+				.map(UUID::toString)
+				.toList();
+	}
+
 	@Builder
 	@Getter
 	class StringBasedIdentifier implements PostfachAddressIdentifier {
diff --git a/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/transfer/PostfachApiFacadeService.java b/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/transfer/PostfachApiFacadeService.java
index e1446a7fe8bdeaf2c4eb7e39b66324650f135314..153b5ebdb9cb5aea52bdcafe56b714f008a622da 100644
--- a/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/transfer/PostfachApiFacadeService.java
+++ b/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/transfer/PostfachApiFacadeService.java
@@ -1,19 +1,18 @@
 package de.ozgcloud.nachrichten.postfach.osiv2.transfer;
 
-import java.util.Collection;
-import java.util.Optional;
+import static de.ozgcloud.nachrichten.postfach.osiv2.transfer.Osi2RequestMapper.*;
+
+import java.util.List;
 import java.util.UUID;
-import java.util.stream.Stream;
 
 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
 import org.springframework.stereotype.Service;
 
 import de.ozgcloud.nachrichten.postfach.PostfachNachricht;
-import de.ozgcloud.nachrichten.postfach.osiv2.OsiPostfachException;
 import de.ozgcloud.nachrichten.postfach.osiv2.config.Osi2PostfachProperties;
 import de.ozgcloud.nachrichten.postfach.osiv2.gen.api.MessageExchangeApi;
-import de.ozgcloud.nachrichten.postfach.osiv2.gen.model.MessageExchangeReceiveMessage;
-import de.ozgcloud.nachrichten.postfach.osiv2.gen.model.MessageExchangeReceiveMessagesResponse;
+import de.ozgcloud.nachrichten.postfach.osiv2.gen.api.QuarantineApi;
+import de.ozgcloud.nachrichten.postfach.osiv2.model.UploadFileMetadata;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.log4j.Log4j2;
 
@@ -24,33 +23,37 @@ import lombok.extern.log4j.Log4j2;
 public class PostfachApiFacadeService {
 
 	private final MessageExchangeApi messageExchangeApi;
-	private final Osi2RequestMapper osi2RequestMapper;
-	private final Osi2ResponseMapper osi2ResponseMapper;
-
-	static final int MAX_NUMBER_RECEIVED_MESSAGES = 100;
+	private final QuarantineApi quarantineApi;
+	private final Osi2RequestMapper requestMapper;
+	private final Osi2ResponseMapper responseMapper;
+	private final Osi2PostfachProperties.ApiConfiguration apiConfiguration;
 
-	public void sendMessage(PostfachNachricht nachricht) {
+	public void sendMessage(PostfachNachricht nachricht, List<UploadFileMetadata> attachments) {
 		messageExchangeApi.sendMessage(
-				osi2RequestMapper.mapMailboxId(nachricht),
-				osi2RequestMapper.mapOutSendMessageRequestV2(nachricht)
+				requestMapper.mapMailboxId(nachricht),
+				requestMapper.mapOutSendMessageRequestV2(nachricht, attachments)
 		);
 	}
 
-	public Stream<PostfachNachricht> receiveMessages() {
-		return Optional.ofNullable(receiveMessagesResponse().getMessages())
-				.stream()
-				.flatMap(Collection::stream)
-				.map(this::fetchMessageByGuid);
+	public void uploadChunk(String uploadId, byte[] chunk) {
+		// TODO
+		//		quarantineApi.uploadChunk(
+		//				requestMapper.mapDomainChunkMetaData(null),
+		//				apiConfiguration.getTenant(),
+		//				apiConfiguration.getNameIdentifier(),
+		//				new ByteArrayResource(chunk)
+		//		);
 	}
-	
-	private MessageExchangeReceiveMessagesResponse receiveMessagesResponse() {
-		return Optional.ofNullable(messageExchangeApi.receiveMessages(MAX_NUMBER_RECEIVED_MESSAGES, 0))
-				.orElseThrow(() -> new OsiPostfachException("Expect non empty response!", null));
+
+	public List<String> fetchPendingMessageIds() {
+		return responseMapper.toMessageIds(
+				messageExchangeApi.receiveMessages(MAX_NUMBER_RECEIVED_MESSAGES, 0)
+		);
 	}
 
-	PostfachNachricht fetchMessageByGuid(final MessageExchangeReceiveMessage message) {
-		var messageReply = messageExchangeApi.getMessage(message.getGuid());
-		return osi2ResponseMapper.toPostfachNachricht(messageReply);
+	public PostfachNachricht fetchMessageById(final String messageId) {
+		var messageReply = messageExchangeApi.getMessage(UUID.fromString(messageId));
+		return responseMapper.toPostfachNachricht(messageReply);
 	}
 
 	public void deleteMessage(final String messageId) {
diff --git a/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/OsiPostfachRemoteServiceTest.java b/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/OsiPostfachRemoteServiceTest.java
index 685c36f61dd8d1d44afc185da5bf94bf3eb4ee67..c21d0be38489cc11cb16dfe1484b57a4e3f7a4f9 100644
--- a/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/OsiPostfachRemoteServiceTest.java
+++ b/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/OsiPostfachRemoteServiceTest.java
@@ -15,7 +15,7 @@ import org.mockito.Spy;
 
 import de.ozgcloud.nachrichten.postfach.PostfachNachricht;
 import de.ozgcloud.nachrichten.postfach.osiv2.factory.PostfachNachrichtTestFactory;
-import de.ozgcloud.nachrichten.postfach.osiv2.transfer.PostfachApiFacadeService;
+import de.ozgcloud.nachrichten.postfach.osiv2.transfer.Osi2PostfachService;
 
 class OsiPostfachRemoteServiceTest {
 
@@ -24,7 +24,7 @@ class OsiPostfachRemoteServiceTest {
 	private OsiPostfachRemoteService osiPostfachRemoteService;
 
 	@Mock
-	private PostfachApiFacadeService postfachApiFacadeService;
+	private Osi2PostfachService osi2PostfachService;
 
 	private final PostfachNachricht nachricht1 = PostfachNachrichtTestFactory.createBuilder()
 			.subject("Nachricht 1")
@@ -40,15 +40,15 @@ class OsiPostfachRemoteServiceTest {
 		@DisplayName("should call send message")
 		@Test
 		void shouldCallSendMessage() {
-			postfachApiFacadeService.sendMessage(nachricht1);
+			osi2PostfachService.sendMessage(nachricht1);
 
-			verify(postfachApiFacadeService).sendMessage(nachricht1);
+			verify(osi2PostfachService).sendMessage(nachricht1);
 		}
 
 		@DisplayName("should throw osi postfach exception on runtime exception")
 		@Test
 		void shouldThrowOsiPostfachExceptionOnRuntimeException() {
-			doThrow(new RuntimeException()).when(postfachApiFacadeService).sendMessage(nachricht1);
+			doThrow(new RuntimeException()).when(osi2PostfachService).sendMessage(nachricht1);
 
 			assertThatThrownBy(() -> osiPostfachRemoteService.sendMessage(nachricht1))
 					.isInstanceOf(OsiPostfachException.class);
@@ -62,7 +62,7 @@ class OsiPostfachRemoteServiceTest {
 		@DisplayName("should return postfach messages")
 		@Test
 		void shouldReturnPostfachMessages() {
-			when(postfachApiFacadeService.receiveMessages()).thenReturn(Stream.of(nachricht1, nachricht2));
+			when(osi2PostfachService.receiveMessages()).thenReturn(Stream.of(nachricht1, nachricht2));
 
 			var result = osiPostfachRemoteService.getAllMessages();
 
@@ -77,15 +77,15 @@ class OsiPostfachRemoteServiceTest {
 		@DisplayName("should call deleteMessage")
 		@Test
 		void shouldCallDeleteMessage() {
-			postfachApiFacadeService.deleteMessage(UUID.randomUUID().toString());
+			osi2PostfachService.deleteMessage(UUID.randomUUID().toString());
 
-			verify(postfachApiFacadeService).deleteMessage(any());
+			verify(osi2PostfachService).deleteMessage(any());
 		}
 
 		@DisplayName("should throw osi postfach exception on runtime exception")
 		@Test
 		void shouldThrowOsiPostfachExceptionOnRuntimeException() {
-			doThrow(new RuntimeException()).when(postfachApiFacadeService).deleteMessage(UUID.randomUUID().toString());
+			doThrow(new RuntimeException()).when(osi2PostfachService).deleteMessage(UUID.randomUUID().toString());
 
 			assertThatThrownBy(() -> osiPostfachRemoteService.deleteMessage(anyString())).isInstanceOf(OsiPostfachException.class);
 		}
diff --git a/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/transfer/Osi2RequestMapperTest.java b/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/transfer/Osi2RequestMapperTest.java
index 2f1cbe4af9940226535af88324de563b10261338..3136b93aa50edef92e299c2f727194550e3d08ec 100644
--- a/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/transfer/Osi2RequestMapperTest.java
+++ b/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/transfer/Osi2RequestMapperTest.java
@@ -2,8 +2,12 @@ package de.ozgcloud.nachrichten.postfach.osiv2.transfer;
 
 import static de.ozgcloud.nachrichten.postfach.osiv2.factory.PostfachAddressTestFactory.*;
 import static de.ozgcloud.nachrichten.postfach.osiv2.factory.PostfachNachrichtTestFactory.*;
+import static de.ozgcloud.nachrichten.postfach.osiv2.transfer.UploadFileMetadataTestFactory.*;
+import static java.util.Collections.*;
 import static org.assertj.core.api.Assertions.*;
 
+import java.util.List;
+import java.util.UUID;
 import java.util.stream.Stream;
 
 import org.junit.jupiter.api.DisplayName;
@@ -19,6 +23,7 @@ import de.ozgcloud.nachrichten.postfach.PostfachAddressIdentifier;
 import de.ozgcloud.nachrichten.postfach.PostfachNachricht;
 import de.ozgcloud.nachrichten.postfach.osiv2.factory.PostfachAddressTestFactory;
 import de.ozgcloud.nachrichten.postfach.osiv2.factory.PostfachNachrichtTestFactory;
+import de.ozgcloud.nachrichten.postfach.osiv2.gen.model.MessageExchangeFiles;
 import de.ozgcloud.nachrichten.postfach.osiv2.gen.model.OutSendMessageRequestV2;
 import de.ozgcloud.nachrichten.postfach.osiv2.gen.model.V1EidasLevel;
 import de.ozgcloud.nachrichten.postfach.osiv2.gen.model.V1ReplyBehavior;
@@ -117,7 +122,7 @@ class Osi2RequestMapperTest {
 					.replyOption(PostfachNachricht.ReplyOption.POSSIBLE)
 					.build();
 
-			var result = mapper.mapOutSendMessageRequestV2(nachricht);
+			var result = mapper.mapOutSendMessageRequestV2(nachricht, emptyList());
 
 			assertThat(result.getReplyAction()).isEqualTo(V1ReplyBehavior.REPLYPOSSIBLE);
 		}
@@ -129,7 +134,7 @@ class Osi2RequestMapperTest {
 					.replyOption(PostfachNachricht.ReplyOption.MANDATORY)
 					.build();
 
-			var result = mapper.mapOutSendMessageRequestV2(nachricht);
+			var result = mapper.mapOutSendMessageRequestV2(nachricht, emptyList());
 
 			assertThat(result.getReplyAction()).isEqualTo(V1ReplyBehavior.REPLYMANDATORY);
 		}
@@ -158,10 +163,38 @@ class Osi2RequestMapperTest {
 			assertThat(result.getIsHtml()).isFalse();
 		}
 
+		@DisplayName("should map files if empty")
+		@Test
+		void shouldMapFilesIfEmpty() {
+			var result = doMapping();
+
+			assertThat(result.getFiles()).isEmpty();
+		}
+
+		@DisplayName("should map two files")
+		@Test
+		void shouldMapTwoFiles() {
+			var files = List.of(
+					UploadFileMetadataTestFactory.create(),
+					UploadFileMetadataTestFactory.createBuilder()
+							.guid(UPLOAD_GUID2)
+							.build()
+			);
+
+			var result = mapper.mapOutSendMessageRequestV2(PostfachNachrichtTestFactory.create(), files);
+
+			assertThat(result.getFiles())
+					.usingRecursiveComparison()
+					.isEqualTo(files.stream().map(mapper::mapMessageExchangeFile).toList());
+		}
+
 		@DisplayName("should map files")
 		@Test
 		void shouldMapFiles() {
-			var result = doMapping();
+			var result = mapper.mapOutSendMessageRequestV2(
+					PostfachNachrichtTestFactory.create(),
+					List.of(UploadFileMetadataTestFactory.create())
+			);
 
 			assertThat(result.getFiles()).isEmpty();
 		}
@@ -175,7 +208,47 @@ class Osi2RequestMapperTest {
 		}
 
 		private OutSendMessageRequestV2 doMapping() {
-			return mapper.mapOutSendMessageRequestV2(PostfachNachrichtTestFactory.create());
+			return mapper.mapOutSendMessageRequestV2(PostfachNachrichtTestFactory.create(), emptyList());
+		}
+	}
+
+	@DisplayName("map message exchange file")
+	@Nested
+	class TestMapMessageExchangeFile {
+		@DisplayName("should map guid")
+		@Test
+		void shouldMapGuid() {
+			var result = mapFile();
+
+			assertThat(result.getGuid()).isEqualTo(UPLOAD_GUID);
+		}
+
+		@DisplayName("should map mimeType")
+		@Test
+		void shouldMapMimeType() {
+			var result = mapFile();
+
+			assertThat(result.getMimeType()).isEqualTo(UPLOAD_CONTENT_TYPE);
+		}
+
+		@DisplayName("should map name")
+		@Test
+		void shouldMapName() {
+			var result = mapFile();
+
+			assertThat(result.getName()).isEqualTo(UPLOAD_NAME);
+		}
+
+		@DisplayName("should map size")
+		@Test
+		void shouldMapSize() {
+			var result = mapFile();
+
+			assertThat(result.getSize()).isEqualTo(UPLOAD_SIZE);
+		}
+
+		private MessageExchangeFiles mapFile() {
+			return mapper.mapMessageExchangeFile(UploadFileMetadataTestFactory.create());
 		}
 	}
 
diff --git a/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/transfer/PostfachApiFacadeServiceTest.java b/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/transfer/PostfachApiFacadeServiceTest.java
index d2ceb286eaf9a6dfe46d5f79841fa0f63b08ea18..395f286e2fe85c7fc49e77469480b78eb5931593 100644
--- a/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/transfer/PostfachApiFacadeServiceTest.java
+++ b/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/transfer/PostfachApiFacadeServiceTest.java
@@ -88,9 +88,9 @@ class PostfachApiFacadeServiceTest {
 			void mock() {
 				when(messageExchangeApi.receiveMessages(anyInt(), anyInt())).thenReturn(response);
 				doReturn(PostfachNachrichtTestFactory.createBuilder().messageId(MESSAGE_ID_1).build())
-						.when(postfachApiFacadeService).fetchMessageByGuid(response.getMessages().get(0));
+						.when(postfachApiFacadeService).fetchMessageById(response.getMessages().get(0));
 				doReturn(PostfachNachrichtTestFactory.createBuilder().messageId(MESSAGE_ID_2).build())
-						.when(postfachApiFacadeService).fetchMessageByGuid(response.getMessages().get(1));
+						.when(postfachApiFacadeService).fetchMessageById(response.getMessages().get(1));
 			}
 
 			@DisplayName("should return")
@@ -146,7 +146,7 @@ class PostfachApiFacadeServiceTest {
 		}
 
 		private List<PostfachNachricht> receiveMessageList() {
-			return postfachApiFacadeService.receiveMessages().toList();
+			return postfachApiFacadeService.fetchPendingMessageIds().toList();
 		}
 
 	}
@@ -164,7 +164,7 @@ class PostfachApiFacadeServiceTest {
 		void shouldCallGetMessage() {
 			when(messageExchangeApi.getMessage(any())).thenReturn(replyMessage);
 
-			postfachApiFacadeService.fetchMessageByGuid(receiveMessage);
+			postfachApiFacadeService.fetchMessageById(receiveMessage);
 
 			verify(messageExchangeApi).getMessage(any());
 		}
@@ -174,7 +174,7 @@ class PostfachApiFacadeServiceTest {
 			when(messageExchangeApi.getMessage(any())).thenReturn(replyMessage);
 			when(osi2ResponseMapper.toPostfachNachricht(any())).thenReturn(PostfachNachrichtTestFactory.create());
 
-			postfachApiFacadeService.fetchMessageByGuid(receiveMessage);
+			postfachApiFacadeService.fetchMessageById(receiveMessage);
 
 			verify(osi2ResponseMapper).toPostfachNachricht(any());
 		}
@@ -184,7 +184,7 @@ class PostfachApiFacadeServiceTest {
 			when(messageExchangeApi.getMessage(any())).thenReturn(replyMessage);
 			when(osi2ResponseMapper.toPostfachNachricht(any())).thenReturn(PostfachNachrichtTestFactory.create());
 
-			var postfachNachricht = postfachApiFacadeService.fetchMessageByGuid(receiveMessage);
+			var postfachNachricht = postfachApiFacadeService.fetchMessageById(receiveMessage);
 
 			assertThat(postfachNachricht).isInstanceOf(PostfachNachricht.class);
 		}
diff --git a/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/transfer/UploadFileMetadataTestFactory.java b/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/transfer/UploadFileMetadataTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..c8be39ba431578990396418ae48a0b216dea3dbb
--- /dev/null
+++ b/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/transfer/UploadFileMetadataTestFactory.java
@@ -0,0 +1,26 @@
+package de.ozgcloud.nachrichten.postfach.osiv2.transfer;
+
+import java.util.UUID;
+
+import de.ozgcloud.nachrichten.postfach.osiv2.model.UploadFileMetadata;
+
+public class UploadFileMetadataTestFactory {
+
+	public static final String UPLOAD_GUID = UUID.randomUUID().toString();
+	public static final String UPLOAD_GUID2 = UUID.randomUUID().toString();
+	public static final String UPLOAD_NAME = "upload.txt";
+	public static final String UPLOAD_CONTENT_TYPE = "text/plain";
+	public static final Long UPLOAD_SIZE = 1001L;
+
+	public static UploadFileMetadata create() {
+		return createBuilder().build();
+	}
+
+	public static UploadFileMetadata.UploadFileMetadataBuilder createBuilder() {
+		return UploadFileMetadata.builder()
+				.guid(UPLOAD_GUID)
+				.name(UPLOAD_NAME)
+				.contentType(UPLOAD_CONTENT_TYPE)
+				.size(UPLOAD_SIZE);
+	}
+}