Skip to content

Commit 2ddcd8f

Browse files
committed
display attachments file
1 parent 6e396a5 commit 2ddcd8f

File tree

4 files changed

+68
-23
lines changed

4 files changed

+68
-23
lines changed

src/components/SmtpServer.vue

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,15 @@ onBeforeMount(() => start())
3030
3131
onMounted(() => {
3232
unlisten.value = listen("new-email", (event: Event<Email>) => {
33+
const payload = event.payload;
3334
const email: Email = {
34-
...event.payload,
35+
...payload,
3536
id: nanoid(),
36-
excerpt: makeExcerpt(event.payload),
37+
excerpt: makeExcerpt(payload),
3738
date: new Date(),
3839
isOpen: false,
39-
links: parseUrls(event.payload.html).map((url) => ({ url, status: 'pending' })),
40+
links: parseUrls(payload.html).map((url) => ({ url, status: 'pending' })),
41+
attachments: payload.attachments,
4042
};
4143
4244
create(email)

src/components/email/Header.vue

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
<script setup lang="ts">
2+
import type { Attachment, Email } from '../../lib/types';
3+
4+
5+
const { email } = defineProps<{
6+
email: Email
7+
}>()
8+
9+
function downloadAttachment(attachment: Attachment) {
10+
// download the attachment.data
11+
const blob = new Blob([attachment.data], { type: attachment.content_type })
12+
const url = URL.createObjectURL(blob)
13+
return url;
14+
}
15+
</script>
16+
<template>
17+
<header class="grid grid-cols-1 px-5 py-3 lg:grid-cols-2 text-sm">
18+
<div class="flex gap-x-5 py-1">
19+
<div class="upp w-24 font-semibold">Subject:</div>
20+
<div class="font-semibold uppercase">{{ email.subject.trim() }}</div>
21+
</div>
22+
<div class="flex gap-x-5 py-1">
23+
<div class="w-24 font-semibold">From:</div>
24+
<div>
25+
{{ email.sender[0] }} {{ `<${email.sender[1]}>` }}
26+
</div>
27+
</div>
28+
<div class="flex gap-x-5 py-1">
29+
<div class="w-24 font-semibold">To:</div>
30+
<div>{{ email.to.join(", ") }}</div>
31+
</div>
32+
<div v-if="email.cc" class="flex gap-x-5 py-1">
33+
<div class="w-24 font-semibold">Cc:</div>
34+
<div>{{ email.cc.join(", ") }}</div>
35+
</div>
36+
37+
<div v-if="email.attachments?.length" class="text-sm lg:col-span-2">
38+
<h3 class="font-medium">Attachments</h3>
39+
<ul class="mt-2 text-xs font-mono gap-y-2">
40+
<li v-for="attachment in email.attachments">
41+
<a :href="downloadAttachment(attachment)" download class="flex gap-2 hover:underline">
42+
<svg class="w-4 h-4 inline-block" aria-hidden="true" fill="none" stroke="currentColor" stroke-width="1.5"
43+
viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
44+
<path
45+
d="M18.375 12.739l-7.693 7.693a4.5 4.5 0 01-6.364-6.364l10.94-10.94A3 3 0 1119.5 7.372L8.552 18.32m.009-.01l-.01.01m5.699-9.941l-7.81 7.81a1.5 1.5 0 002.112 2.13"
46+
stroke-linecap="round" stroke-linejoin="round"></path>
47+
</svg>
48+
{{ attachment.filename }}
49+
</a>
50+
</li>
51+
</ul>
52+
</div>
53+
</header>
54+
</template>

src/lib/types.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,15 @@ export interface Email {
1313
isOpen: boolean;
1414
links: EmailLink[];
1515
spamScore?: number;
16+
attachments?: Attachment[];
1617
};
1718

19+
export interface Attachment {
20+
filename: string,
21+
content_type: string,
22+
data: string,
23+
}
24+
1825
export type EmailLinkStatus = 'ok' | 'error' | 'pending'
1926

2027
export interface EmailLink {

src/views/Email.vue

Lines changed: 2 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { watch, ref, onMounted } from 'vue'
44
import { useAppStore } from '../stores/appStore';
55
import type { Email } from '../lib/types';
66
import BodyTabs from '../components/email/BodyTabs.vue'
7+
import Header from '../components/email/Header.vue';
78
import router from '../route';
89
910
const props = defineProps<{
@@ -78,26 +79,7 @@ function deleteEmail() {
7879
</div>
7980
</div>
8081

81-
<header class="grid grid-cols-1 px-5 py-3 lg:grid-cols-2 text-sm">
82-
<div class="flex gap-x-5 py-1">
83-
<div class="upp w-24 font-semibold">Subject:</div>
84-
<div class="font-semibold uppercase">{{ email.subject.trim() }}</div>
85-
</div>
86-
<div class="flex gap-x-5 py-1">
87-
<div class="w-24 font-semibold">From:</div>
88-
<div>
89-
{{ email.sender[0] }} {{ `<${email.sender[1]}>` }}
90-
</div>
91-
</div>
92-
<div class="flex gap-x-5 py-1">
93-
<div class="w-24 font-semibold">To:</div>
94-
<div>{{ email.to.join(", ") }}</div>
95-
</div>
96-
<div v-if="email.cc" class="flex gap-x-5 py-1">
97-
<div class="w-24 font-semibold">Cc:</div>
98-
<div>{{ email.cc.join(", ") }}</div>
99-
</div>
100-
</header>
82+
<Header :email="email" />
10183

10284
<main class="relative h-full w-full">
10385
<BodyTabs :email="email" />

0 commit comments

Comments
 (0)