diff --git a/pom.xml b/pom.xml
index 935366a3ccd1f75db7dfeb8ec60f8986ddfd3388..4310022fcf6b7ccaf3c32f2e64439365000d885b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -91,17 +91,27 @@
 			<artifactId>mapstruct</artifactId>
 		</dependency>
 
-		<!-- Test -->
 		<dependency>
 			<groupId>org.projectlombok</groupId>
 			<artifactId>lombok</artifactId>
 			<scope>provided</scope>
 		</dependency>
+		<!-- Test -->
 		<dependency>
 			<groupId>org.mockito</groupId>
 			<artifactId>mockito-core</artifactId>
 			<scope>test</scope>
 		</dependency>
+		<dependency>
+			<groupId>org.yaml</groupId>
+			<artifactId>snakeyaml</artifactId>
+			<scope>test</scope>
+		</dependency>
+
+		<dependency>
+			<groupId>org.apache.commons</groupId>
+			<artifactId>commons-collections4</artifactId>
+		</dependency>
 		<dependency>
 			<groupId>org.mockito</groupId>
 			<artifactId>mockito-junit-jupiter</artifactId>
diff --git a/src/main/java/de/ozgcloud/xta/client/model/XtaMessage.java b/src/main/java/de/ozgcloud/xta/client/model/XtaMessage.java
index 39f333a24d76af9071651b323d8ce9077eb145a1..10cf16eb90b271057680c386fde04af0956da777 100644
--- a/src/main/java/de/ozgcloud/xta/client/model/XtaMessage.java
+++ b/src/main/java/de/ozgcloud/xta/client/model/XtaMessage.java
@@ -7,7 +7,7 @@ import jakarta.validation.constraints.NotNull;
 
 import lombok.Builder;
 
-@Builder
+@Builder(toBuilder = true)
 public record XtaMessage(
 		@NotNull @Valid XtaMessageMetaData metaData,
 		@NotNull @Valid XtaFile messageFile,
diff --git a/src/main/java/de/ozgcloud/xta/client/model/XtaMessageMetaData.java b/src/main/java/de/ozgcloud/xta/client/model/XtaMessageMetaData.java
index 5f1943e41d77cfc1f8124595efd23f59f730bc12..87fee1fb81f3729aa310ccfe06dd12820a899320 100644
--- a/src/main/java/de/ozgcloud/xta/client/model/XtaMessageMetaData.java
+++ b/src/main/java/de/ozgcloud/xta/client/model/XtaMessageMetaData.java
@@ -9,7 +9,7 @@ import jakarta.validation.constraints.PositiveOrZero;
 
 import lombok.Builder;
 
-@Builder
+@Builder(toBuilder = true)
 public record XtaMessageMetaData(
 		@NotBlank String service,
 		@NotBlank String businessScenarioCode,
diff --git a/src/test/java/de/ozgcloud/xta/client/XtaDevServerSetupExtension.java b/src/test/java/de/ozgcloud/xta/client/XtaDevServerSetupExtension.java
index 6eeca9bb83b1d3741e95a154df8165321b77a716..032410d619fd57c1b1f74b0d705626a8372dbd48 100644
--- a/src/test/java/de/ozgcloud/xta/client/XtaDevServerSetupExtension.java
+++ b/src/test/java/de/ozgcloud/xta/client/XtaDevServerSetupExtension.java
@@ -17,6 +17,7 @@ import de.ozgcloud.xta.client.model.XtaMessageMetaData;
 import de.ozgcloud.xta.client.model.XtaMessageMetaDataTestFactory;
 import de.ozgcloud.xta.client.model.XtaMessageTestFactory;
 import genv3.de.xoev.transport.xta.x211.ParameterIsNotValidException;
+import genv3.de.xoev.transport.xta.x211.PermissionDeniedException;
 import lombok.Getter;
 import lombok.Setter;
 import lombok.SneakyThrows;
@@ -33,7 +34,8 @@ public class XtaDevServerSetupExtension implements BeforeAllCallback, BeforeEach
 	private XtaClientFactory clientFactory;
 
 	static final String BASE_URL = "https://li33-0005.dp.dsecurecloud.de/MB_XTA-WS/XTA210";
-	static final String CLIENT_IDENTIFIER1 = "dp:012345678910_XtaClientITCase1";
+	// static final String CLIENT_IDENTIFIER1 = "dp:012345678910_XtaClientITCase1";
+	static final String CLIENT_IDENTIFIER1 = "afmsh:ozg-cloud-dev001";
 	static final String CLIENT_IDENTIFIER2 = "dp:012345678910_XtaClientITCase2";
 
 	@Override
@@ -84,19 +86,25 @@ public class XtaDevServerSetupExtension implements BeforeAllCallback, BeforeEach
 	@SneakyThrows
 	void sendTestMessageToClient2(Identifier author, Identifier reader) {
 		var messageId = service.createMessageId(author);
+		var message = XtaMessageExampleLoader.load(
+				XtaMessageExampleLoader.MessageExampleConfig.builder()
+						.messageLabel("versammlungsanzeige_with_attachment")
+						.messageId(messageId)
+						.author(author)
+						.reader(reader)
+						.build());
 		try {
-			service.sendMessage(XtaMessageTestFactory.createBuilder()
-					.metaData(XtaMessageMetaDataTestFactory.createBuilder()
-							.authorIdentifier(author)
-							.readerIdentifier(reader)
-							.messageId(messageId)
-							.build())
-					.build()
-			);
+			log.info("Sending from author {} to reader {}.", message.metaData().authorIdentifier(), message.metaData().readerIdentifier());
+			service.sendMessage(message);
 		} catch (ParameterIsNotValidException e) {
 			log.error("Failed to send test message to client2: {}", e.getFaultInfo().getErrorCode().getName());
 			throw e;
+
+		} catch (PermissionDeniedException e) {
+			log.error("Failed to send test message to client2: {}", e.getFaultInfo().getErrorCode().getName());
+			throw e;
 		}
+
 	}
 
 	@SneakyThrows
diff --git a/src/test/java/de/ozgcloud/xta/client/XtaMessageExampleLoader.java b/src/test/java/de/ozgcloud/xta/client/XtaMessageExampleLoader.java
new file mode 100644
index 0000000000000000000000000000000000000000..a3737c9c5ba980f87914835826f9615b12d70eeb
--- /dev/null
+++ b/src/test/java/de/ozgcloud/xta/client/XtaMessageExampleLoader.java
@@ -0,0 +1,125 @@
+package de.ozgcloud.xta.client;
+
+import java.io.IOException;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.function.Function;
+import java.util.function.Supplier;
+
+import jakarta.activation.DataHandler;
+import jakarta.annotation.Nullable;
+import jakarta.mail.util.ByteArrayDataSource;
+import jakarta.validation.constraints.NotBlank;
+
+import org.apache.commons.collections4.MapUtils;
+import org.apache.commons.io.IOUtils;
+import org.yaml.snakeyaml.Yaml;
+
+import de.ozgcloud.xta.client.model.Identifier;
+import de.ozgcloud.xta.client.model.XtaFile;
+import de.ozgcloud.xta.client.model.XtaMessage;
+import de.ozgcloud.xta.client.model.XtaMessageMetaData;
+import lombok.Builder;
+
+public class XtaMessageExampleLoader {
+
+	static Yaml yaml = new Yaml();
+
+	@SuppressWarnings("unchecked")
+	public static XtaMessage load(MessageExampleConfig config) {
+		var messageDataMap = loadXtaMessageDataMap(config.messageLabel);
+
+		return XtaMessage.builder()
+				.metaData(mapXtaMessageMetadata(getChild(messageDataMap, "metaData"), config))
+				.messageFile(mapXtaFile(getChild(messageDataMap, "messageFile"), config.messageLabel + "/message"))
+				.attachmentFiles(mapXtaFiles((List<Map<String, Object>>) messageDataMap.get("attachmentFiles"), config.messageLabel + "/attachment"))
+				.build();
+	}
+
+	@Builder
+	public record MessageExampleConfig(
+			@NotBlank String messageLabel,
+			@Nullable String messageId,
+			@Nullable Identifier author,
+			@Nullable Identifier reader) {
+	}
+
+	@SuppressWarnings("unchecked")
+	private static Map<String, Object> getChild(Map<String, Object> parent, String key) {
+		return Objects.requireNonNull((Map<String, Object>) MapUtils.getMap(parent, key), "Missing key: %s".formatted(key));
+	}
+
+	private static XtaFile mapXtaFile(Map<String, Object> messageFile, String resourcePrefix) {
+		Function<String, String> getString = key -> Objects.requireNonNull(
+				MapUtils.getString(messageFile, key), "[Failed mapping for %s] Missing key: %s".formatted(resourcePrefix, key));
+
+		return XtaFile.builder()
+				.name(getString.apply("name"))
+				.contentType(getString.apply("contentType"))
+				.content(createContentDataHandler(getMessageResourcePath(resourcePrefix, getString.apply("name"))))
+				.build();
+	}
+
+	private static List<XtaFile> mapXtaFiles(List<Map<String, Object>> attachmentFiles, String resourcePrefix) {
+		return attachmentFiles.stream()
+				.map(messageFileMap -> mapXtaFile(messageFileMap, resourcePrefix))
+				.toList();
+	}
+
+	private static XtaMessageMetaData mapXtaMessageMetadata(Map<String, Object> metaData, MessageExampleConfig config) {
+		Function<String, String> getString = key -> Objects.requireNonNull(
+				MapUtils.getString(metaData, key), "metaData key missing: %s".formatted(key));
+		return XtaMessageMetaData.builder()
+				.service(getString.apply("service"))
+				.businessScenarioCode(getString.apply("businessScenarioCode"))
+				.messageTypeCode(getString.apply("messageTypeCode"))
+				.messageTypePayloadSchema(getString.apply("messageTypePayloadSchema"))
+				.messageId(getIfConfigNull(
+						config.messageId, () -> getString.apply("messageId")))
+				.authorIdentifier(getIfConfigNull(
+						config.author,
+						() -> mapIdentifier(getChild(metaData, "authorIdentifier"))))
+				.readerIdentifier(getIfConfigNull(
+						config.reader,
+						() -> mapIdentifier(getChild(metaData, "readerIdentifier"))))
+				.build();
+	}
+
+	private static <T> T getIfConfigNull(T configValue, Supplier<T> supplier) {
+		return configValue != null ? configValue : supplier.get();
+	}
+
+	private static Identifier mapIdentifier(Map<String, Object> identifier) {
+		Function<String, String> getString = key -> (String) identifier.get(key);
+		return Identifier.builder()
+				.name(getString.apply("name"))
+				.value(getString.apply("value"))
+				.category(getString.apply("category"))
+				.build();
+	}
+
+	private static LinkedHashMap<String, Object> loadXtaMessageDataMap(String messageLabel) {
+		var yamlFileData = readBytesFromResource(getMessageResourcePath(messageLabel, "xta-message.yaml"));
+		return yaml.load(new String(yamlFileData));
+	}
+
+	private static String getMessageResourcePath(String prefix, String suffix) {
+		return "/messages/%s/%s".formatted(prefix, suffix);
+	}
+
+	private static DataHandler createContentDataHandler(String resourcePath) {
+		var data = readBytesFromResource(resourcePath);
+		return new DataHandler(new ByteArrayDataSource(data, "application/octet-stream"));
+	}
+
+	private static byte[] readBytesFromResource(String path) {
+		try {
+			return IOUtils.toByteArray(Objects.requireNonNull(XtaMessageExampleLoader.class.getResourceAsStream(path)));
+		} catch (IOException e) {
+			throw new RuntimeException(e);
+		}
+	}
+
+}
diff --git a/src/test/resources/messages/versammlungsanzeige_with_attachment/attachment/VO_EutinKarte.png b/src/test/resources/messages/versammlungsanzeige_with_attachment/attachment/VO_EutinKarte.png
new file mode 100644
index 0000000000000000000000000000000000000000..164a96d0c3334cf72bb417cd4a680e3324b46d82
Binary files /dev/null and b/src/test/resources/messages/versammlungsanzeige_with_attachment/attachment/VO_EutinKarte.png differ
diff --git a/src/test/resources/messages/versammlungsanzeige_with_attachment/attachment/WE_EutinPlatz.jpg b/src/test/resources/messages/versammlungsanzeige_with_attachment/attachment/WE_EutinPlatz.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..52f1b4269a2b72c7a294d33bd16d287e902a6809
Binary files /dev/null and b/src/test/resources/messages/versammlungsanzeige_with_attachment/attachment/WE_EutinPlatz.jpg differ
diff --git a/src/test/resources/messages/versammlungsanzeige_with_attachment/attachment/WE_EutinSitztPlatz.jpg b/src/test/resources/messages/versammlungsanzeige_with_attachment/attachment/WE_EutinSitztPlatz.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..741838f4520c3dc3e00e7a6704f5beee294ed786
Binary files /dev/null and b/src/test/resources/messages/versammlungsanzeige_with_attachment/attachment/WE_EutinSitztPlatz.jpg differ
diff --git a/src/test/resources/messages/versammlungsanzeige_with_attachment/message/Antrag.xml b/src/test/resources/messages/versammlungsanzeige_with_attachment/message/Antrag.xml
new file mode 100644
index 0000000000000000000000000000000000000000..d6443d8c0c7cfef391fb24d72df9142d877af611
--- /dev/null
+++ b/src/test/resources/messages/versammlungsanzeige_with_attachment/message/Antrag.xml
@@ -0,0 +1 @@
+<fim.S17000652.17000652001004 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="urn:xoev-de:xfall:standard:fim-s17000652_1.4"><G17003529><G05001479><G05001480><F05002750>d70979eb-0ab4-4f0b-81f8-1b7d3acb590b</F05002750><F05002751>23.07.2024 16:13:13</F05002751><F05002752>fim.S17000652.17000652001004</F05002752><F05002753>urn:fim:Versammlungsanzeige:1.4</F05002753></G05001480><G05001481><F05002754>Fachdienst Sicherheit und Ordnung</F05002754><F05002755>vbe:010550120100</F05002755><F05002756>Versammlungsbehörde</F05002756></G05001481><G05001482><F05002754>Dataport</F05002754><F05002755>ehp:010100100000</F05002755><F05002756>Versammlungsbehörde</F05002756></G05001482></G05001479><F17005454>true</F17005454><F17005455>false</F17005455><F17005533>d70979eb-0ab4-4f0b-81f8-1b7d3acb590b</F17005533></G17003529><F17009191>true</F17009191><G17005403><G17007200><F60000319>OrgName</F60000319><F17011809>OrgUnit</F17011809><G60000086><F60000243>OrgSteet</F60000243><F60000244>OrgNum</F60000244><F60000246>33333</F60000246><F60000247>OrgCity</F60000247></G60000086></G17007200><G17007201><F60000228>ContactName</F60000228><F60000227>ContactSureName</F60000227><F60000240>3334343444</F60000240><F60000242>Ansprechemail@example.com</F60000242></G17007201><G17002127><F60000228>VerantwortungVorname</F60000228><F60000227>VerantwortungNachname</F60000227><G60000086><F60000243>VerantwortungStraße</F60000243><F60000244>VerHNum</F60000244><F60000246>22222</F60000246><F60000247>VerOrt</F60000247><F60000248>VerAddresszusatz</F60000248></G60000086><F60000242>Verantwortungemail@example.com</F60000242></G17002127></G17005403><F17003371>Anzeigen einer ortsfesten Versammlung (Kundgebung / Demonstration)</F17003371><G17005404><G17007202><F17003373>Den Hintern platt sitzen</F17003373><F17011810>Vom Stehen ins Sitzen kommen!</F17011810><F17003377>Auf der Stelle</F17003377><G17005405><F60000296>VO_EutinKarte.png</F60000296></G17005405><G17005406><F60000048>2024-09-29</F60000048><F17001348>12.25</F17001348><F60000049>2024-09-29</F60000049><F17001349>13.75</F17001349></G17005406></G17007202><G17007205><F17003379>5</F17003379><F17003380>1</F17003380><F17003382>Tisch-Test-Unternehmen</F17003382><G17007234><F17011826>Keine</F17011826></G17007234><G17007235><F17011827>Keine</F17011827></G17007235><G17007210><F60000296>WE_EutinPlatz.jpg</F60000296><F60000296>WE_EutinSitztPlatz.jpg</F60000296></G17007210></G17007205></G17005404></fim.S17000652.17000652001004>
\ No newline at end of file
diff --git a/src/test/resources/messages/versammlungsanzeige_with_attachment/xta-message.yaml b/src/test/resources/messages/versammlungsanzeige_with_attachment/xta-message.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..7796c3993d28f83b36b8cc095874dd624deb463f
--- /dev/null
+++ b/src/test/resources/messages/versammlungsanzeige_with_attachment/xta-message.yaml
@@ -0,0 +1,26 @@
+metaData:
+  service: urn:fim:Versammlungsanzeige:1.4
+  businessScenarioCode: FIM_DATA
+  messageTypeCode: fim.S17000652.17000652001004
+  messageTypePayloadSchema: urn:xoev-de:xfall:standard:fim-s17000652_1.4
+  authorIdentifier:
+    name: Dataport
+    category: Engagement- und Hobbyportal
+    value: ehp:010100100000
+  readerIdentifier:
+    name: L100012.OE.279550874
+    category: Versammlungsbehörde
+    value: afmsh:010600000000_Online-Dienste
+messageFile:
+  contentType: application/xml
+  name: Antrag.xml
+attachmentFiles:
+  - contentType: image/png
+    name: VO_EutinKarte.png
+    id: 0d929408-7c89-43ae-a303-71165be7b775
+  - contentType: image/jpeg
+    name: WE_EutinPlatz.jpg
+    id: 175faaa1-1410-4a4d-8677-0f2984f5ed4e
+  - contentType: image/jpeg
+    name: WE_EutinSitztPlatz.jpg
+    id: 1734b13e-50b4-4367-954a-ee8da0c5348c
\ No newline at end of file