Initial draft for HTTP file upload.

This commit is contained in:
Franz Heinzmann (Frando)
2020-06-09 23:53:21 +02:00
parent e08e817988
commit b0330f5c0a
4 changed files with 47 additions and 2 deletions

View File

@@ -3,6 +3,7 @@
//! This module implements a job queue maintained in the SQLite database
//! and job types.
use std::env;
use std::fmt;
use std::future::Future;
@@ -31,6 +32,7 @@ use crate::message::{self, Message, MessageState};
use crate::mimefactory::MimeFactory;
use crate::param::*;
use crate::smtp::Smtp;
use crate::upload::upload_file;
use crate::{scheduler::InterruptInfo, sql};
// results in ~3 weeks for the last backoff timespan
@@ -726,7 +728,25 @@ pub async fn send_msg_job(context: &Context, msg_id: MsgId) -> Result<Option<Job
}
};
let mimefactory = MimeFactory::from_msg(context, &msg, attach_selfavatar).await?;
// Upload file if DCC_UPLOAD_URL is set.
// See upload-server folder for an example.
// TODO: Move into send_msg_to_smtp job.
let mut did_upload_file = false;
if let Some(file) = msg.get_file(context) {
if let Ok(endpoint) = env::var("DCC_UPLOAD_URL") {
info!(context, "Upload file attachement to {}", endpoint);
let file_url = upload_file(context, endpoint, file).await?;
let text = msg.text.clone().unwrap_or("".into());
let suffix = format!("\n\nFile attachement: {}", file_url);
msg.set_text(Some(format!("{}{}", text, suffix)));
did_upload_file = true;
}
}
let mut mimefactory = MimeFactory::from_msg(context, &msg, attach_selfavatar).await?;
if did_upload_file {
mimefactory.set_include_file(false);
}
let mut recipients = mimefactory.recipients();

View File

@@ -67,6 +67,7 @@ mod simplify;
mod smtp;
pub mod stock;
mod token;
pub(crate) mod upload;
#[macro_use]
mod dehtml;

View File

@@ -50,6 +50,7 @@ pub struct MimeFactory<'a, 'b> {
context: &'a Context,
last_added_location_id: u32,
attach_selfavatar: bool,
include_file: bool,
}
/// Result of rendering a message, ready to be submitted to a send job.
@@ -159,6 +160,7 @@ impl<'a, 'b> MimeFactory<'a, 'b> {
last_added_location_id: 0,
attach_selfavatar,
context,
include_file: true,
};
Ok(factory)
}
@@ -206,6 +208,7 @@ impl<'a, 'b> MimeFactory<'a, 'b> {
req_mdn: false,
last_added_location_id: 0,
attach_selfavatar: false,
include_file: true,
};
Ok(res)
@@ -409,6 +412,10 @@ impl<'a, 'b> MimeFactory<'a, 'b> {
.collect()
}
pub fn set_include_file(&mut self, include_file: bool) {
self.include_file = include_file
}
pub async fn render(mut self) -> Result<RenderedEmail, Error> {
// Headers that are encrypted
// - Chat-*, except Chat-Version
@@ -900,7 +907,7 @@ impl<'a, 'b> MimeFactory<'a, 'b> {
let mut parts = Vec::new();
// add attachment part
if chat::msgtype_has_file(self.msg.viewtype) {
if chat::msgtype_has_file(self.msg.viewtype) && self.include_file {
if !is_file_size_okay(context, &self.msg).await {
bail!(
"Message exceeds the recommended {} MB.",

17
src/upload.rs Normal file
View File

@@ -0,0 +1,17 @@
use crate::context::Context;
use crate::error::{bail, Result};
use async_std::path::PathBuf;
/// Upload file to a HTTP upload endpoint.
pub async fn upload_file(_context: &Context, endpoint: String, file: PathBuf) -> Result<String> {
// TODO: Use tokens for upload, encrypt file with PGP.
let response = surf::post(endpoint).body_file(file)?.await;
if let Err(err) = response {
bail!("Upload failed: {}", err);
}
let mut response = response.unwrap();
match response.body_string().await {
Ok(string) => Ok(string),
Err(err) => bail!("Invalid response from upload: {}", err),
}
}